/*
 *      Interactive disassembler (IDA).
 *      Copyright (c) 1990-96 by Ilfak Guilfanov.
 *      ALL RIGHTS RESERVED.
 *                              FIDO:   2:5020/209
 *                              E-mail: ig@estar.msk.su
 *
 */

#include "i5.hpp"

//----------------------------------------------------------------------
inline void GetImm(op_t &x) {
  x.type = o_imm;
  x.value = ua_next_byte();
}

//------------------------------------------------------------------------
inline void op_c(op_t &x) {
  x.type = o_phrase;
  x.phrase = R_c;
}

//------------------------------------------------------------------------
static void op_ad(op_t &x) {
  x.type = o_near;
  x.addr = ua_next_word();
}

static void op_ss(op_t &x);
static void op_dd(op_t &x);
static void op_a(op_t &x);
static void op_e(op_t &x);
static void op_nn(op_t &x);
static void op_ad(op_t &x);
static void op_n(op_t &x);
static void op_mm(op_t &x);
static void op_r2(op_t &x);
static void op_r1(op_t &x);
static void z80_ixcommands(int _isx);
static void z80_misc(void);
static bool z380_ED(void);

static int code;

static int W [] =    { I5_add,I5_adc,I5_sub,I5_sbb,I5_ana,I5_xra,I5_ora,I5_cmp };
static int Wi[] =    { I5_adi,I5_aci,I5_sui,I5_sbi,I5_ani,I5_xri,I5_ori,I5_cpi };
static int calls[] = { I5_cnz,I5_cz, I5_cnc,I5_cc, I5_cpo,I5_cpe,I5_cp, I5_cm  };
static int jumps[] = { I5_jnz,I5_jz, I5_jnc,I5_jc, I5_jpo,I5_jpe,I5_jp, I5_jm  };
static int rets [] = { I5_rnz,I5_rz, I5_rnc,I5_rc, I5_rpo,I5_rpe,I5_rp, I5_rm  };
static int rols [] = { I5_rlc,I5_rrc,I5_ral,I5_rar,I5_daa,I5_cma,I5_stc,I5_cmc };
static int CBrols[]= { Z80_rlc,Z80_rrc,Z80_rl,Z80_rr,Z80_sla,Z80_sra,Z80_srr,Z80_srl };
static int Zrols[] = { Z80_rlca,Z80_rrca,Z80_rla,Z80_rra,I5_daa,Z80_cpl,Z80_scf,Z80_ccf };

//----------------------------------------------------------------------
static void ConvertToFunny(void) {
  switch ( cmd.itype ) {
    case I5_mov:
      cmd.Op1.set_showed();
      cmd.Op2.set_showed();
      if ( cmd.Op1.type == o_reg && cmd.Op2.type == o_mem ) {
        switch ( cmd.Op1.reg ) {
          case R_bc:
            cmd.itype = A80_lbcd;
            cmd.Op1.clr_showed();
            break;
          case R_de:
            cmd.itype = A80_lded;
            cmd.Op1.clr_showed();
            break;
          case R_sp:
            cmd.itype = A80_lspd;
            cmd.Op1.clr_showed();
            break;
          case R_ix:
            cmd.itype = A80_lixd;
            cmd.Op1.clr_showed();
            break;
          case R_iy:
            cmd.itype = A80_liyd;
            cmd.Op1.clr_showed();
            break;
        }
      }
      if ( cmd.Op1.type == o_mem && cmd.Op2.type == o_reg ) {
        switch ( cmd.Op2.reg ) {
          case R_bc:
            cmd.itype = A80_sbcd;
            cmd.Op2.clr_showed();
            break;
          case R_de:
            cmd.itype = A80_sded;
            cmd.Op2.clr_showed();
            break;
          case R_sp:
            cmd.itype = A80_sspd;
            cmd.Op2.clr_showed();
            break;
          case R_ix:
            cmd.itype = A80_sixd;
            cmd.Op2.clr_showed();
            break;
          case R_iy:
            cmd.itype = A80_siyd;
            cmd.Op2.clr_showed();
            break;
        }
      }
      if ( cmd.Op1.type == o_reg && cmd.Op2.type == o_reg ) {
        switch ( cmd.Op1.reg ) {
          case R_sp:
            if ( cmd.Op2.reg == R_ix ) {
              cmd.Op1.clr_showed();
              cmd.Op2.clr_showed();
              cmd.itype = A80_spix;
            }
            if ( cmd.Op2.reg == R_iy ) {
              cmd.Op1.clr_showed();
              cmd.Op2.clr_showed();
              cmd.itype = A80_spiy;
            }
            break;
          case R_r:
            cmd.itype = A80_mvra;
            cmd.Op1.clr_showed();
            cmd.Op2.clr_showed();
            break;
          case R_i:
            cmd.itype = A80_mvia;
            cmd.Op1.clr_showed();
            cmd.Op2.clr_showed();
            break;
          case R_a:
            if ( cmd.Op2.reg == R_r ) {
              cmd.itype = A80_mvar;
              cmd.Op1.clr_showed();
              cmd.Op2.clr_showed();
            }
            if ( cmd.Op2.reg == R_i ) {
              cmd.itype = A80_mvai;
              cmd.Op1.clr_showed();
              cmd.Op2.clr_showed();
            }
            break;
        }
      }
      break;    /* mov */
    case Z80_jp:
      if ( cmd.Op2.type == o_phrase && cmd.Op2.phrase == R_ix ) {
        cmd.itype = A80_pcix;
        cmd.Op2.clr_showed();
        break;
      }
      if ( cmd.Op2.type == o_phrase && cmd.Op2.phrase == R_iy ) {
        cmd.itype = A80_pciy;
        cmd.Op2.clr_showed();
        break;
      }
      break;    /* jp */
    case Z80_ex:
      cmd.Op1.clr_showed();
      cmd.Op2.clr_showed();
      if ( cmd.Op2.reg == R_ix ) cmd.itype = A80_xtix;
      if ( cmd.Op2.reg == R_iy ) cmd.itype = A80_xtiy;
      break;    /* ex */
    case I5_in:
      if ( cmd.Op2.type == o_phrase && cmd.Op2.reg == R_c ) {
        cmd.itype = Z80_inp;
        cmd.Op2.clr_showed();
      }
      break;
    case I5_out:
      if ( cmd.Op1.type == o_phrase && cmd.Op1.reg == R_c ) {
        cmd.itype = Z80_outp;
        cmd.Op1.clr_showed();
      }
      break;
    case Z80_cpl:       cmd.itype = I5_cma;             break;
    case Z80_scf:       cmd.itype = I5_stc;             break;
    case Z80_ccf:       cmd.itype = I5_cmc;             break;
    case I5_add:
      if ( cmd.Op1.type == o_reg && cmd.Op1.reg == R_ix ) {
        cmd.itype = A80_addix;
        cmd.Op1.clr_showed();
        if ( cmd.Op2.type == o_reg && cmd.Op2.reg == R_ix ) cmd.Op2.reg = R_hl;
        break;
      }
      if ( cmd.Op1.type == o_reg && cmd.Op1.reg == R_iy ) {
        cmd.itype = A80_addiy;
        cmd.Op1.clr_showed();
        if ( cmd.Op2.type == o_reg && cmd.Op2.reg == R_iy ) cmd.Op2.reg = R_hl;
        break;
      }
      break;
    case I5_adc:
      if ( cmd.Op1.dtyp == dt_word && cmd.Op1.type == o_reg ) {
        cmd.itype = A80_addc;
        cmd.Op1.clr_showed();
        if ( cmd.Op1.reg == R_ix ) cmd.itype = A80_addcix;
        if ( cmd.Op1.reg == R_iy ) cmd.itype = A80_addciy;
        if ( cmd.Op2.type == o_reg && cmd.Op1.reg == cmd.Op2.reg ) cmd.Op2.reg = R_hl;
      }
      break;
    case Z80_sbc:
      if ( cmd.Op1.dtyp == dt_word && cmd.Op1.type == o_reg ) {
        cmd.itype = A80_subc;
        cmd.Op1.clr_showed();
        if ( cmd.Op1.reg == R_ix ) cmd.itype = A80_subcix;
        if ( cmd.Op1.reg == R_iy ) cmd.itype = A80_subciy;
        if ( cmd.Op2.type == o_reg && cmd.Op1.reg == cmd.Op2.reg ) cmd.Op2.reg = R_hl;
      }
      break;
    case Z80_jr:
      cmd.Op1.clr_showed();
      switch ( cmd.Op1.Cond ) {
        case oc_c:      cmd.itype = A80_jrc;    break;
        case oc_nc:     cmd.itype = A80_jrnc;   break;
        case oc_z:      cmd.itype = A80_jrz;    break;
        case oc_nz:     cmd.itype = A80_jrnz;   break;
      }
      break;
    case Z80_rrca:      cmd.itype = I5_rrc;     break;
    case Z80_rlca:      cmd.itype = I5_rlc;     break;
    case Z80_rla:       cmd.itype = I5_ral;     break;
    case Z80_rl:        cmd.itype = I5_ral;     break;
    case Z80_rra:       cmd.itype = I5_rar;     break;
    case Z80_rr:        cmd.itype = I5_rar;     break;
    case Z80_cpi:       cmd.itype = A80_cmpi;   break;
    case Z80_cpd:       cmd.itype = A80_cmpd;   break;
    case Z80_outi:      cmd.itype = A80_oti;    break;
    case Z80_outd:      cmd.itype = A80_otd;    break;
    case Z80_inc:       cmd.itype = I5_inr;     break;
    case Z80_dec:       cmd.itype = I5_dcr;     break;
    case Z80_im:
      if ( cmd.Op1.value == 0 ) cmd.itype = A80_im0;
      else if ( cmd.Op1.value == 1 ) cmd.itype = A80_im1;
      else cmd.itype = A80_im2;
      cmd.Op1.clr_showed();
      break;
  }
}

//----------------------------------------------------------------------
static void ConvertToZ80(void)
{
  int cc;
  if ( cmd.itype < Z80_and )
  {
    cmd.Op1.set_showed();
    cmd.Op2.set_showed();
  }
  switch ( cmd.itype )
  {
    case I5_aci:        cmd.itype = I5_adc;     break;
    case I5_adi:
    case I5_dad:        cmd.itype = I5_add;     break;
    case I5_cmp:
    case I5_cpi:
      cmd.itype = Z80_cp;
      if ( !isZ380() ) cmd.Op1.clr_showed();
      break;
    case I5_ana:
    case I5_ani:
      cmd.itype = Z80_and;
      if ( !isZ380() ) cmd.Op1.clr_showed();
      break;
    case I5_ora:
    case I5_ori:
      cmd.itype = Z80_or;
      if ( !isZ380() ) cmd.Op1.clr_showed();
      break;
    case I5_xra:
    case I5_xri:
      cmd.itype = Z80_xor;
      if ( !isZ380() ) cmd.Op1.clr_showed();
      break;
    case I5_sbi:
    case I5_sbb:
      cmd.itype = Z80_sbc;
      break;
    case I5_sui:
    case I5_sub:
      cmd.itype = I5_sub;
      if ( !isZ380() ) cmd.Op1.clr_showed();
      break;
    case I5_dcr:
    case I5_dcx:        cmd.itype = Z80_dec;    break;
    case I5_inr:
    case I5_inx:        cmd.itype = Z80_inc;    break;
    case I5_halt:       cmd.itype = Z80_halt;   break;
    case I5_sphl:
    case I5_mov:
    case I5_mvi:
    case I5_ldax:
    case I5_lxi:
    case I5_lhld:
    case I5_shld:
    case I5_sta:
    case I5_stax:
    case I5_lda:        cmd.itype = Z80_ld;     break;
    case I5_xchg:
    case I5_xthl:       cmd.itype = Z80_ex;     break;
    case I5_pchl:
      cmd.Op1.type = o_phrase;
      cmd.Op1.reg = R_hl;
      cc = oc_not;
      goto zjump;

    case I5_call:       cc = oc_not;goto zcall;
    case I5_cnz:        cc = oc_nz; goto zcall;
    case I5_cz:         cc = oc_z;  goto zcall;
    case I5_cnc:        cc = oc_nc; goto zcall;
    case I5_cc:         cc = oc_c;  goto zcall;
    case I5_cpo:        cc = oc_po; goto zcall;
    case I5_cpe:        cc = oc_pe; goto zcall;
    case I5_cp:         cc = oc_p;  goto zcall;
    case I5_cm:         cc = oc_m;  goto zcall;
    case I5_jmp:        cc = oc_not;goto zjump;
    case I5_jnz:        cc = oc_nz; goto zjump;
    case I5_jz:         cc = oc_z;  goto zjump;
    case I5_jnc:        cc = oc_nc; goto zjump;
    case I5_jc:         cc = oc_c;  goto zjump;
    case I5_jpo:        cc = oc_po; goto zjump;
    case I5_jpe:        cc = oc_pe; goto zjump;
    case I5_jp:         cc = oc_p;  goto zjump;
    case I5_jm:         cc = oc_m;  goto zjump;
    case I5_ret:        cc = oc_not;goto zret;
    case I5_rnz:        cc = oc_nz; goto zret;
    case I5_rz:         cc = oc_z;  goto zret;
    case I5_rnc:        cc = oc_nc; goto zret;
    case I5_rc:         cc = oc_c;  goto zret;
    case I5_rpo:        cc = oc_po; goto zret;
    case I5_rpe:        cc = oc_pe; goto zret;
    case I5_rp:         cc = oc_p;  goto zret;
    case I5_rm:         cc = oc_m;  goto zret;

zret:
      cmd.itype = Z80_ret;
      goto zcc;
zjump:
      cmd.itype = Z80_jp;
      goto zcc;
zcall:
      cmd.itype = Z80_call;
      goto zcc;
zcc:
      cmd.Op2 = cmd.Op1;
      cmd.Op2.n = 1;
      cmd.Op1.type = o_cond;
      cmd.Op1.Cond = cc;
      break;

  }
}

//----------------------------------------------------------------------
static bool is_gameboy_insn(void)
{
  switch ( cmd.itype )
  {
    case Z80_adc:
    case Z80_add:
    case Z80_and:
    case Z80_bit:
    case Z80_call:
    case Z80_ccf:
    case Z80_cp:
    case Z80_cpl:
    case I5_daa:
    case Z80_dec:
    case Z80_di:
    case Z80_ei:
    case Z80_halt:
    case Z80_inc:
    case Z80_jp:
    case Z80_jr:
    case Z80_ld:
    case Z80_ldd:
    case Z80_ldi:
    case I5_nop:
    case Z80_or:
    case Z80_pop:
    case Z80_push:
    case Z80_res:
    case Z80_ret:
    case Z80_reti:
    case Z80_rl:
    case Z80_rla:
    case Z80_rlc:
    case Z80_rlca:
    case Z80_rr:
    case Z80_rra:
    case Z80_rrc:
    case Z80_rrca:
    case I5_rst:
    case Z80_sbc:
    case Z80_scf:
    case Z80_set:
    case Z80_sla:
    case Z80_sra:
    case Z80_srl:
    case Z80_sub:
    case Z80_swap:
    case Z80_xor:
      break;
    default:
      return false;
  }
  return true;
}

//----------------------------------------------------------------------
static void swap_operands(void)
{
  op_t op = cmd.Op1;
  cmd.Op1 = cmd.Op2;
  cmd.Op2 = op;
}

//----------------------------------------------------------------------
int i5_ana(void)
{
  cmd.Op1.dtyp = dt_byte;
  cmd.Op2.dtyp = dt_byte;
  cmd.itype = I5_null;

  code = ua_next_byte();

  switch ( code & 0xC0 )
  {
    case 0x00:
        switch ( code & 0xF )
        {
        case 0:
        case 8:
          {
            int sub = ( code >> 3 ) & 7;
            switch ( sub ) {
              case 0:
                cmd.itype = I5_nop;
                break;
              case 1:                   // 08
                if ( isZ80() )
                {
                  cmd.itype = Z80_ex;
                  cmd.Op1.type  = o_reg;
                  cmd.Op1.reg = R_af;
                  cmd.Op2.type  = o_reg;
                  cmd.Op2.reg = R_af2;
                }
                else
                {
                  cmd.itype = I5_dsub;  // undoc
                }
                break;
              case 2:                   // 10
                if ( isZ80() )
                {
                  cmd.itype = Z80_djnz;
                  op_e(cmd.Op1);
                }
                else
                {
                  cmd.itype = I5_arhl;  // undoc
                }
                break;
              case 3:                   // 18
                if ( isZ80() )
                {
Z80_COMMON:
                  static int conds[] = { 0,1,2,oc_not,oc_nz,oc_z,oc_nc,oc_c };
                  cmd.Op1.Cond = conds[sub];
                  cmd.itype = Z80_jr;
                  cmd.Op1.type = o_cond;
                  op_e(cmd.Op2);
                  break;
                }
                cmd.itype = I5_rdel;  // undoc
                break;
              case 4:                   // 20
                if ( isZ80() ) goto Z80_COMMON;
                cmd.itype = I5_rim;
                break;
              case 5:                   // 28
                if ( isZ80() ) goto Z80_COMMON;
                cmd.itype = I5_ldhi;  // undoc
                GetImm(cmd.Op1);
                break;
              case 6:                   // 30
                if ( isZ80() ) goto Z80_COMMON;
                cmd.itype = I5_sim;
                break;
              case 7:                   // 38
                if ( isZ80() ) goto Z80_COMMON;
                cmd.itype = I5_ldsi;
                GetImm(cmd.Op1);
                break;
            }
          }
          break;
        case 1:
          cmd.itype = I5_lxi;
          op_ss(cmd.Op1);
          op_nn(cmd.Op2);
          break;

        case 9:
          cmd.itype = I5_dad;
          cmd.Op1.reg = R_hl;
          cmd.Op1.dtyp = dt_word;
          cmd.Op1.type = o_reg;
          cmd.Op1.clr_showed();
          op_ss(cmd.Op2);
          break;
        case 0xA:
          if ( (code & 0x20) == 0 ) {
            cmd.itype = I5_ldax;
            cmd.Op2.type = o_phrase;
            cmd.Op2.phrase = R_bc + ((code >> 4) & 1);
            op_a(cmd.Op1);
          } else {
            cmd.Op1.type = o_reg;
            if ( (code & 0x10) == 0 ) {
              cmd.itype = I5_lhld;
              cmd.Op1.dtyp = dt_word;
              cmd.Op2.dtyp = dt_word;
              cmd.Op1.reg = R_hl;
            } else {
              cmd.itype = I5_lda;
              cmd.Op1.reg = R_a;
            }
            op_mm(cmd.Op2);
          }
          cmd.Op1.clr_showed();
          break;
        case 2:
          if ( (code & 0x20) == 0 ) {
            cmd.itype = I5_stax;
            cmd.Op1.type = o_phrase;
            cmd.Op1.phrase = R_bc + ((code >> 4) & 1);
            op_a(cmd.Op2);
          } else {
            cmd.Op2.type = o_reg;
            if ( (code & 0x10) == 0 ) {
              cmd.itype = I5_shld;
              cmd.Op1.dtyp = dt_word;
              cmd.Op2.dtyp = dt_word;
              cmd.Op2.reg = R_hl;
            } else {
              cmd.itype = I5_sta;
              cmd.Op2.reg = R_a;
            }
            op_mm(cmd.Op1);
          }
          cmd.Op2.clr_showed();
          break;
        case 3:
          cmd.itype = I5_inx;
          op_ss(cmd.Op1);
          break;
        case 0xB:
          cmd.itype = I5_dcx;
          op_ss(cmd.Op1);
          break;
        case 4:
        case 0xC:
          cmd.itype = I5_inr;
          op_r1(cmd.Op1);
          break;
        case 5:
        case 0xD:
          cmd.itype = I5_dcr;
          op_r1(cmd.Op1);
          break;
        case 6:
        case 0xE:
          cmd.itype = I5_mvi;
          op_r1(cmd.Op1);
          op_n (cmd.Op2);
          break;
        case 7:
        case 0xF:
          cmd.itype = (isZ80() ? Zrols : rols) [ (code >> 3) & 7 ];
          break;
        }
        break;
    case 0x40:
        cmd.itype = I5_halt;
        if ( code != 0x76 ) {
          cmd.itype = I5_mov;
          op_r1(cmd.Op1);
          op_r2(cmd.Op2);
        }
        break;
    case 0x80:
        op_r2(cmd.Op2);
common:
        cmd.Op1.type  = o_reg;
        cmd.Op1.reg = R_a;
        cmd.itype = (cmd.Op2.type == o_imm ? Wi : W) [ (code >> 3) & 7 ];
        cmd.Op1.clr_showed();
        break;
    case 0xC0:                          /* 11?????? */
        switch ( code & 0xF ) {
          case 0x0:
          case 0x8:                     /* 11???000 */
RETS:
            cmd.itype = rets[ (code >> 3) & 7 ];
            break;
          case 0x2:
          case 0xA:                     /* 11???010 */
JUMPS:
            cmd.itype = jumps[ (code >> 3) & 7 ];
            op_ad(cmd.Op1);
            break;
          case 0x3:
          case 0xB:                     /* 11???011 */
            switch ( ( code >> 3 ) & 7 ) {
              case 0:                   /* 11000011=C3 */
                cmd.itype = I5_jmp;
                op_ad(cmd.Op1);
                break;
              case 1:                   // 11001011=CB - Z80 extensions
                if ( isZ80() )
                {
                  code = ua_next_byte();
                  int fn = (code>>6);
                  if ( fn == 0 )
                  {
                    op_r2(cmd.Op1);
                    cmd.itype = CBrols[ (code>>3) & 7 ];
                    if ( cmd.itype == Z80_srr )
                    {
                      if ( isZ380() )
                      {
                        cmd.itype = Z80_ex;
                        op_r2(cmd.Op2);
                        cmd.Op2.reg += R_b2;
                      }
                    }
                  }
                  else
                  {
                    static int brs[] = { 0, Z80_bit,Z80_res,Z80_set };
                    cmd.itype = brs[fn];
                    cmd.Op1.type = o_imm;
                    cmd.Op1.value = (code>>3) & 7;
                    op_r2(cmd.Op2);
                  }
                }
                else
                {
                  cmd.itype = I5_rstv;  // undoc
                }
                break;
              case 2:                   /* 11010011=D3 */
                cmd.itype = I5_out;
                op_a(cmd.Op2);
                op_n(cmd.Op1);
                break;
              case 3:                   // DB
                cmd.itype = I5_in;
                op_a(cmd.Op1);
                op_n(cmd.Op2);
                break;
              case 4:                   // E3
                cmd.itype = I5_xthl;
                cmd.Op1.type = o_phrase;
                cmd.Op1.reg = R_sp;
                cmd.Op1.clr_showed();
                cmd.Op2.type = o_reg;
                cmd.Op2.reg = R_hl;
                cmd.Op2.clr_showed();
                break;
              case 5:                   // EB
                cmd.itype = I5_xchg;
                cmd.Op1.type = o_reg;
                cmd.Op1.reg = R_de;
                cmd.Op1.clr_showed();
                cmd.Op2.type = o_reg;
                cmd.Op2.reg = R_hl;
                cmd.Op2.clr_showed();
                break;
              case 6:                   // F3
                cmd.itype = I5_di;
                break;
              case 7:                   // FB
                cmd.itype = I5_ei;
                break;
            }
            break;
          case 0x4:
          case 0xC:                     /* 11???100 */
            cmd.itype = calls[ (code >> 3) & 7 ];
            op_ad(cmd.Op1);
            break;
          case 0x1:
          case 0x5:                     // 11????01
            cmd.itype = (code & 4) ? I5_push : I5_pop;
            op_dd(cmd.Op1);
            break;
          case 0x6:
          case 0xE:                     // 11???110
            op_n(cmd.Op2);
            goto common;
          case 0x7:
          case 0xF:                     // 11???111
            cmd.itype = I5_rst;
            cmd.Op1.type = o_imm;
            cmd.Op1.value = (code >> 3) & 7;
            if ( isZ80() )
            { // workaround for bcb6 bug:
              uval_t x = cmd.Op1.value;
              x <<= 3;
              cmd.Op1.value = x;
            }
            break;
          case 0x9:
            switch ( (code >> 4) & 3 ) {
              case 0:
                cmd.itype = I5_ret;     // 11001001 = C9
                break;
              case 1:                   // 11011001 = D9
                if ( isZ80() )
                  cmd.itype = Z80_exx;
                else
                  cmd.itype = I5_shlx;  // undoc
                break;
              case 2:
                cmd.itype = I5_pchl;
                break;
              case 3:
                cmd.itype = I5_sphl;
                cmd.Op1.type = o_reg;
                cmd.Op1.reg = R_sp;
                cmd.Op1.clr_showed();
                cmd.Op2.type = o_reg;
                cmd.Op2.reg = R_hl;
                cmd.Op2.clr_showed();
                break;
            }
            break;
          case 0xD:                     /* 11??1101 */
            switch ( (code >> 4) & 3 ) {
              case 0:
                cmd.itype = I5_call;
                op_ad(cmd.Op1);
                break;
              case 1:           // 11011101 = DD - Z80 extensions
                if ( is8085() )
                {
                  cmd.itype = I5_jnx5;   // undoc
                  op_ad(cmd.Op1);
                }
                else
                {
                  z80_ixcommands(1);
                }
                break;
              case 2:           // 11101101 = ED - Z80 extensions
                if ( isZ380() )
                  z380_ED();
                else if ( is8085() )
                  cmd.itype = I5_lhlx;  // undoc
                else
                  z80_misc();
                break;
              case 3:           // 11111101 = FD - Z80 extensions
                if ( is8085() )
                {
                  cmd.itype = I5_jx5;   // undoc
                  op_ad(cmd.Op1);
                }
                else
                {
                  z80_ixcommands(0);
                }
                break;
            }
            break;
        }
        break;
  }

  if ( cmd.itype == I5_null ) return 0;

  if ( isZ80() )
  {
    if ( ash.uflag & UAS_FUNNY )
      ConvertToFunny();
    else
      ConvertToZ80();
  }

  return cmd.size;

}

//------------------------------------------------------------------------
static void op_r1(op_t &x)
{
  int mode = (code >> 3) & 7;
  if ( mode == 6 ) {
    x.type = o_phrase;
    x.phrase = R_hl;
  } else {
    x.type = o_reg;
    x.reg = mode;
  }
}

//------------------------------------------------------------------------
static void op_r2(op_t &x) {
  int mode = code & 7;
  if ( mode == 6 ) {
    x.type = o_phrase;
    x.phrase = R_hl;
  } else {
    x.type = o_reg;
    x.reg = mode;
  }
}

//------------------------------------------------------------------------
static void op_ss(op_t &x) {
  int ss = (code >> 4) & 3;
  x.type = o_reg;
  x.dtyp = dt_word;
  x.reg = ss + R_bc;
  if ( ss == 3 ) x.reg = R_sp;
}

//------------------------------------------------------------------------
static void op_dd(op_t &x) {
  int ss = (code >> 4) & 3;
  x.type = o_reg;
  x.dtyp = dt_word;
  x.reg = ss + R_bc;
}

//------------------------------------------------------------------------
static void op_nn(op_t &x) {
  x.type = o_imm;
  x.dtyp = dt_word;
  x.value = ua_next_word();
}

//------------------------------------------------------------------------
static void op_n(op_t &x) {
  x.type = o_imm;
  x.value = ua_next_byte();
}

//------------------------------------------------------------------------
static void op_e(op_t &x) {
  x.type = o_near;
  sval_t rel = char(ua_next_byte());
  x.addr = ushort(cmd.ip + cmd.size + rel);
}

//------------------------------------------------------------------------
static void op_a(op_t &x) {
  x.type = o_reg;
  x.reg = R_a;
  x.clr_showed();
}

//------------------------------------------------------------------------
static void op_mm(op_t &x) {
  x.type = o_mem;
  x.addr = ua_next_word();
}

static char isx;
//------------------------------------------------------------------------
static void op_xdispl(op_t &x) {
  x.type = o_displ;
  x.phrase = isx ? R_ix : R_iy;
  x.addr = ua_next_byte();
}

//------------------------------------------------------------------------
static void op_ix(op_t &x) {
  x.type = o_reg;
  x.reg = isx ? R_ix : R_iy;
  x.dtyp = dt_word;
}

//------------------------------------------------------------------------
static void op_f(op_t &x)
{
  x.type = o_reg;
  x.dtyp = dt_byte;
  x.reg  = R_f;
}

//------------------------------------------------------------------------
static void op_ibyte(op_t &x,int low) {
  x.type = o_reg;
  x.reg = isx
                ? (low ? R_xl : R_xh)
                : (low ? R_yl : R_yh);
}

//------------------------------------------------------------------------
static int op_xbytereg(op_t &x,int mode)
{
  if ( mode == 6 )
  {
    x.type = o_phrase;
    x.phrase = R_hl;
    return 1;
  } else {
    if ( mode == R_h ) op_ibyte(x,0);
    else if ( mode == R_l ) op_ibyte(x,1);
    else {
      x.type = o_reg;
      x.reg = mode;
    }
    return 0;
  }
}

//------------------------------------------------------------------------
static int op_xr1(op_t &x)
{
  return op_xbytereg(x,(code >> 3) & 7);
}

//------------------------------------------------------------------------
static int op_xr2(op_t &x)
{
  return op_xbytereg(x,code & 7);
}

//------------------------------------------------------------------------
struct insndesc_t
{
  uchar code;
  ushort itype;
  uchar op1;
  uchar op2;
};

#define rA      R_a+1
#define rB      R_b+1
#define rC      R_c+1
#define rD      R_d+1
#define rE      R_e+1
#define rH      R_h+1
#define rL      R_l+1
#define rI      R_i+1
#define rW      R_w+1
#define rR      R_r+1
#define rBC     R_bc+1
#define rDE     R_de+1
#define rHL     R_hl+1
#define rIX     R_ix+1
#define rIY     R_iy+1
#define rSP     R_sp+1
#define rLW     R_lw+1
#define rIXL    R_ixl+1
#define rIXU    R_ixu+1
#define rDSR    R_dsr+1
#define rXSR    R_xsr+1
#define rIYL    R_iyl+1
#define rIYU    R_iyu+1
#define rYSR    R_ysr+1
#define rSR     R_sr+1
#define rIB     R_ib+1
#define rIW     R_iw+1
#define rXM     R_xm+1
#define rLCK    R_lck+1
#define rBC2    R_bc2+1
#define rDE2    R_de2+1
#define rHL2    R_hl2+1
#define rIX2    R_ix2+1
#define rIY2    R_iy2+1

#define atBC    0x30
#define atDE    0x31
#define atHL    0x32
#define atSP    0x33
#define atIX    0x34
#define atIY    0x35
#define atC     0x36
#define rip8    0x37    // ip relative displ 8bits
#define rip16   0x38    // ip relative displ 16bits
#define rip24   0x39    // ip relative displ 24bits
#define imm8    0x3A    // 8bit immval
#define imm16   0x3B    // 16bit immval
#define mem16   0x3C    // (1234h)

#define ix8     0x40    // (IX+12)
#define iy8     0x41    // (IY+12)
#define ixs     0x42    // (IX+saved_value)
#define iys     0x43    // (IY+saved_value)
#define sps     0x44    // (SP+saved_value)

// condition codes
#define ccNZ    0x50
#define ccZ     0x51
#define ccNC    0x52
#define ccC     0x53
#define ccPO    0x54
#define ccPE    0x55
#define ccP     0x56
#define ccM     0x57

#define c0      0x60
#define c1      0x61
#define c2      0x62
#define c3      0x63
#define c4      0x64
#define c5      0x65
#define c6      0x66
#define c7      0x67

static insndesc_t cmdsDD[] = {
{ 0x01, Z80_ld,     atBC,       rIX         },
{ 0x02, Z80_ld,     rBC,        rDE         },
{ 0x03, Z80_ld,     rIX,        atBC        },
{ 0x07, Z80_ld,     rIX,        rBC         },
{ 0x09, Z80_add,    rIX,        rBC         },
{ 0x0B, Z80_ld,     rBC,        rIX         },
{ 0x0C, Z80_ld,     rBC,        atBC        },
{ 0x0D, Z80_ld,     rBC,        atDE        },
{ 0x0F, Z80_ld,     rBC,        atHL        },
{ 0x10, Z80_djnz,   rip16                   },
{ 0x11, Z80_ld,     atDE,       rIX         },
{ 0x12, Z80_ld,     rDE,        rDE         },
{ 0x13, Z80_ld,     rIX,        atDE        },
{ 0x17, Z80_ld,     rIX,        rDE         },
{ 0x18, Z80_jr,     rip16                   },
{ 0x19, Z80_add,    rIX,        rDE         },
{ 0x1B, Z80_ld,     rDE,        rIX         },
{ 0x1C, Z80_ld,     rDE,        atBC        },
{ 0x1D, Z80_ld,     rDE,        atDE        },
{ 0x1F, Z80_ld,     rDE,        atHL        },
{ 0x20, Z80_jr,     ccNZ,       rip16       },
{ 0x21, Z80_ld,     rIX,        imm16       },
{ 0x22, Z80_ld,     mem16,      rIX         },
{ 0x23, Z80_inc,    rIX                     },
{ 0x24, Z80_inc,    rIXU                    },
{ 0x25, Z80_dec,    rIXU                    },
{ 0x26, Z80_ld,     rIXU,       imm8        },
{ 0x27, Z80_ld,     rIX,        rIY         },
{ 0x28, Z80_jr,     ccZ,        rip16       },
{ 0x29, Z80_add,    rIX,        rIX         },
{ 0x2A, Z80_ld,     rIX,        mem16       },
{ 0x2B, Z80_dec,    rIX                     },
{ 0x2C, Z80_inc,    rIXL                    },
{ 0x2D, Z80_dec,    rIXL                    },
{ 0x2E, Z80_ld,     rIXL,       imm8        },
{ 0x2F, Z80_cplw,   rHL                     },
{ 0x30, Z80_jr,     ccNC,       rip16       },
{ 0x31, Z80_ld,     atHL,       rIX         },
{ 0x32, Z80_ld,     rHL,        rDE         },
{ 0x33, Z80_ld,     rIX,        atHL        },
{ 0x34, Z80_inc,    ix8                     },
{ 0x35, Z80_dec,    ix8                     },
{ 0x36, Z80_ld,     ix8,        imm8        },
{ 0x37, Z80_ld,     rIX,        rHL         },
{ 0x38, Z80_jr,     ccC,        rip16       },
{ 0x39, Z80_add,    rIX,        rSP         },
{ 0x3B, Z80_ld,     rHL,        rIX         },
{ 0x3C, Z80_ld,     rHL,        atBC        },
{ 0x3D, Z80_ld,     rHL,        atDE        },
{ 0x3E, Z80_swap,   rIX                     },
{ 0x3F, Z80_ld,     rHL,        atHL        },
{ 0x40, Z80_inw,    rBC,        atC         },
{ 0x41, Z80_outw,   atC,        rBC         },
{ 0x44, Z80_ld,     rB,         rIXU        },
{ 0x45, Z80_ld,     rB,         rIXL        },
{ 0x46, Z80_ld,     rB,         ix8         },
{ 0x47, Z80_ldw,    rI,         rHL         },
{ 0x4C, Z80_ld,     rC,         rIXU        },
{ 0x4D, Z80_ld,     rC,         rIXL        },
{ 0x4E, Z80_ld,     rC,         ix8         },
{ 0x50, Z80_inw,    rDE,        atC         },
{ 0x51, Z80_outw,   atC,        rDE         },
{ 0x54, Z80_ld,     rD,         rIXU        },
{ 0x55, Z80_ld,     rD,         rIXL        },
{ 0x56, Z80_ld,     rD,         ix8         },
{ 0x57, Z80_ldw,    rHL,        rI          },
{ 0x5D, Z80_ld,     rE,         rIXL        },
{ 0x5E, Z80_ld,     rE,         ix8         },
{ 0x60, Z80_ld,     rIXU,       rB          },
{ 0x61, Z80_ld,     rIXU,       rC          },
{ 0x62, Z80_ld,     rIXU,       rD          },
{ 0x63, Z80_ld,     rIXU,       rE          },
{ 0x64, Z80_ld,     rIXU,       rIXU        },
{ 0x65, Z80_ld,     rIXU,       rIXL        },
{ 0x66, Z80_ld,     rH,         ix8         },
{ 0x67, Z80_ld,     rIXU,       rA          },
{ 0x68, Z80_ld,     rIXL,       rB          },
{ 0x69, Z80_ld,     rIXL,       rC          },
{ 0x6A, Z80_ld,     rIXL,       rD          },
{ 0x6B, Z80_ld,     rIXL,       rE          },
{ 0x6C, Z80_ld,     rIXL,       rIXU        },
{ 0x6D, Z80_ld,     rIXL,       rIXL        },
{ 0x6E, Z80_ld,     rL,         ix8         },
{ 0x6F, Z80_ld,     rIXL,       rA          },
{ 0x70, Z80_ld,     ix8,        rB          },
{ 0x71, Z80_ld,     ix8,        rC          },
{ 0x72, Z80_ld,     ix8,        rD          },
{ 0x73, Z80_ld,     ix8,        rE          },
{ 0x74, Z80_ld,     ix8,        rH          },
{ 0x75, Z80_ld,     ix8,        rL          },
{ 0x77, Z80_ld,     ix8,        rA          },
{ 0x78, Z80_inw,    rHL,        atC         },
{ 0x79, Z80_outw,   atC,        rHL         },
{ 0x7C, Z80_ld,     rA,         rIXU        },
{ 0x7D, Z80_ld,     rA,         rIXL        },
{ 0x7E, Z80_ld,     rA,         ix8         },
{ 0x84, Z80_add,    rA,         rIXU        },
{ 0x85, Z80_add,    rA,         rIXL        },
{ 0x86, Z80_add,    rA,         ix8         },
{ 0x87, Z80_addw,   rHL,        rIX         },
{ 0x8C, Z80_adc,    rA,         rIXU        },
{ 0x8D, Z80_adc,    rA,         rIXL        },
{ 0x8E, Z80_adc,    rA,         ix8         },
{ 0x8F, Z80_adcw,   rHL,        rIX         },
{ 0x94, Z80_sub,    rA,         rIXU        },
{ 0x95, Z80_sub,    rA,         rIXL        },
{ 0x96, Z80_sub,    rA,         ix8         },
{ 0x97, Z80_subw,   rHL,        rIX         },
{ 0x9C, Z80_sbc,    rA,         rIXU        },
{ 0x9D, Z80_sbc,    rA,         rIXL        },
{ 0x9E, Z80_sbc,    rA,         ix8         },
{ 0x9F, Z80_sbcw,   rHL,        rIX         },
{ 0xA4, Z80_and,    rA,         rIXU        },
{ 0xA5, Z80_and,    rA,         rIXL        },
{ 0xA6, Z80_and,    rA,         ix8         },
{ 0xA7, Z80_andw,   rHL,        rIX         },
{ 0xAC, Z80_xor,    rA,         rIXU        },
{ 0xAD, Z80_xor,    rA,         rIXL        },
{ 0xAE, Z80_xor,    rA,         ix8         },
{ 0xAF, Z80_xorw,   rHL,        rIX         },
{ 0xB4, Z80_or,     rA,         rIXU        },
{ 0xB5, Z80_or,     rA,         rIXL        },
{ 0xB6, Z80_or,     rA,         ix8         },
{ 0xB7, Z80_orw,    rHL,        rIX         },
{ 0xBC, Z80_cp,     rA,         rIXU        },
{ 0xBD, Z80_cp,     rA,         rIXL        },
{ 0xBE, Z80_cp,     rA,         ix8         },
{ 0xBF, Z80_cpw,    rHL,        rIX         },
{ 0xC0, Z80_ddir,   rW                      },
{ 0xC1, Z80_ddir,   rIB,        rW          },
{ 0xC2, Z80_ddir,   rIW,        rW          },
{ 0xC3, Z80_ddir,   rIB                     },
{ 0xC4, Z80_calr,   ccNZ,       rip16       },
{ 0xC6, Z80_addw,   rHL,        ix8         },
{ 0xC8, Z80_ldctl,  rSR,        rA          },
{ 0xCA, Z80_ldctl,  rSR,        imm8        },
{ 0xCC, Z80_calr,   ccZ,        rip16       },
{ 0xCD, Z80_calr,   rip16                   },
{ 0xCE, Z80_adcw,   rHL,        ix8         },
{ 0xCF, Z80_mtest,                          },
{ 0xD0, Z80_ldctl,  rA,         rXSR        },
{ 0xD4, Z80_calr,   ccNC,       rip16       },
{ 0xD6, Z80_subw,   rHL,        ix8         },
{ 0xD8, Z80_ldctl,  rXSR,       rA          },
{ 0xD9, Z80_exxx,                           },
{ 0xDA, Z80_ldctl,  rXSR,       imm8        },
{ 0xDC, Z80_calr,   ccC,        rip16       },
{ 0xDE, Z80_sbcw,   rHL,        ix8         },
{ 0xE1, Z80_pop,    rIX                     },
{ 0xE3, Z80_ex,     atSP,       rIX         },
{ 0xE4, Z80_calr,   ccPO,       rip16       },
{ 0xE5, Z80_push,   rIX                     },
{ 0xE6, Z80_andw,   rHL,        ix8         },
{ 0xE9, Z80_jp,     atIX                    },
{ 0xEC, Z80_calr,   ccPE,       rip16       },
{ 0xEE, Z80_xorw,   rHL,        ix8         },
{ 0xF3, Z80_di,     imm8                    },
{ 0xF4, Z80_calr,   ccP,        rip16       },
{ 0xF6, Z80_orw,    rHL,        ix8         },
{ 0xF7, Z80_setc,   rLW                     },
{ 0xF9, Z80_ld,     rSP,        rIX         },
{ 0xFB, Z80_ei,     imm8                    },
{ 0xFC, Z80_calr,   ccM,        rip16       },
{ 0xFE, Z80_cpw,    rHL,        ix8         },
{ 0xFF, Z80_resc,   rLW                     },
{ 0x00, 0 },
};

//the next byte after DDBC is in saved_value
static insndesc_t cmdsDDCB[] = {
{ 0x01, Z80_ld,     rBC,        sps         },
{ 0x02, Z80_rlcw,   ixs                     },
{ 0x03, Z80_ld,     rBC,        ixs         },
{ 0x06, Z80_rlc,    ixs                     },
{ 0x09, Z80_ld,     sps,        rBC         },
{ 0x0A, Z80_rrcw,   ixs                     },
{ 0x0B, Z80_ld,     ixs,        rBC         },
{ 0x0E, Z80_rrc,    ixs                     },
{ 0x11, Z80_ld,     rDE,        sps         },
{ 0x12, Z80_rlw,    ixs                     },
{ 0x13, Z80_ld,     rDE,        ixs         },
{ 0x16, Z80_rl,     ixs                     },
{ 0x19, Z80_ld,     sps,        rDE         },
{ 0x1A, Z80_rrw,    ixs                     },
{ 0x1B, Z80_ld,     ixs,        rDE         },
{ 0x1E, Z80_rr,     ixs                     },
{ 0x21, Z80_ld,     rIX,        sps         },
{ 0x22, Z80_slaw,   ixs                     },
{ 0x23, Z80_ld,     rIY,        ixs         },
{ 0x26, Z80_sla,    ixs                     },
{ 0x29, Z80_ld,     sps,        rIX         },
{ 0x2A, Z80_sraw,   ixs                     },
{ 0x2B, Z80_ld,     ixs,        rIY         },
{ 0x2E, Z80_sra,    ixs                     },
{ 0x31, Z80_ld,     rHL,        sps         },
{ 0x33, Z80_ld,     rHL,        ixs         },
{ 0x39, Z80_ld,     sps,        rHL         },
{ 0x3A, Z80_srlw,   ixs                     },
{ 0x3B, Z80_ld,     ixs,        rHL         },
{ 0x3E, Z80_srl,    ixs                     },
{ 0x46, Z80_bit,    c0,         ixs         },
{ 0x4E, Z80_bit,    c1,         ixs         },
{ 0x56, Z80_bit,    c2,         ixs         },
{ 0x5E, Z80_bit,    c3,         ixs         },
{ 0x66, Z80_bit,    c4,         ixs         },
{ 0x6E, Z80_bit,    c5,         ixs         },
{ 0x76, Z80_bit,    c6,         ixs         },
{ 0x7E, Z80_bit,    c7,         ixs         },
{ 0x86, Z80_res,    c0,         ixs         },
{ 0x8E, Z80_res,    c1,         ixs         },
{ 0x92, Z80_multw,  ixs                     },
{ 0x92, Z80_multw,  rHL,        ixs         },
{ 0x96, Z80_res,    c2,         ixs         },
{ 0x9A, Z80_multuw, ixs                     },
{ 0x9A, Z80_multuw, rHL,        ixs         },
{ 0x9E, Z80_res,    c3,         ixs         },
{ 0xA6, Z80_res,    c4,         ixs         },
{ 0xAE, Z80_res,    c5,         ixs         },
{ 0xB6, Z80_res,    c6,         ixs         },
{ 0xBA, Z80_divuw,  ixs                     },
{ 0xBA, Z80_divuw,  rHL,        ixs         },
{ 0xBE, Z80_res,    c7,         ixs         },
{ 0xC6, Z80_set,    c0,         ixs         },
{ 0xCE, Z80_set,    c1,         ixs         },
{ 0xD6, Z80_set,    c2,         ixs         },
{ 0xDE, Z80_set,    c3,         ixs         },
{ 0xE6, Z80_set,    c4,         ixs         },
{ 0xEE, Z80_set,    c5,         ixs         },
{ 0xF6, Z80_set,    c6,         ixs         },
{ 0xFE, Z80_set,    c7,         ixs         },
{ 0x00, 0 },
};


static insndesc_t cmdsFD[] = {
{ 0x01, Z80_ld,     atBC,       rIY         },
{ 0x02, Z80_ld,     rBC,        rHL         },
{ 0x03, Z80_ld,     rIY,        atBC        },
{ 0x07, Z80_ld,     rIY,        rBC         },
{ 0x09, Z80_add,    rIY,        rBC         },
{ 0x0B, Z80_ld,     rBC,        rIY         },
{ 0x0C, Z80_ld,     atBC,       rBC         },
{ 0x0D, Z80_ld,     atDE,       rBC         },
{ 0x0F, Z80_ld,     atHL,       rBC         },
{ 0x10, Z80_djnz,   rip24                   },
{ 0x11, Z80_ld,     atDE,       rIY         },
{ 0x12, Z80_ld,     rDE,        rHL         },
{ 0x13, Z80_ld,     rIY,        atDE        },
{ 0x17, Z80_ld,     rIY,        rDE         },
{ 0x18, Z80_jr,     rip24                   },
{ 0x19, Z80_add,    rIY,        rDE         },
{ 0x1B, Z80_ld,     rDE,        rIY         },
{ 0x1C, Z80_ld,     atBC,       rDE         },
{ 0x1D, Z80_ld,     atDE,       rDE         },
{ 0x1F, Z80_ld,     atHL,       rDE         },
{ 0x20, Z80_jr,     ccNZ,       rip24       },
{ 0x21, Z80_ld,     rIY,        imm16       },
{ 0x22, Z80_ld,     mem16,      rIY         },
{ 0x23, Z80_inc,    rIY                     },
{ 0x24, Z80_inc,    rIYU                    },
{ 0x25, Z80_dec,    rIYU                    },
{ 0x26, Z80_ld,     rIYU,       imm8        },
{ 0x27, Z80_ld,     rIY,        rIX         },
{ 0x28, Z80_jr,     ccZ,        rip24       },
{ 0x29, Z80_add,    rIY,        rIY         },
{ 0x2A, Z80_ld,     rIY,        mem16       },
{ 0x2B, Z80_dec,    rIY                     },
{ 0x2C, Z80_inc,    rIYL                    },
{ 0x2D, Z80_dec,    rIYL                    },
{ 0x2E, Z80_ld,     rIYL,       imm8        },
{ 0x30, Z80_jr,     ccNC,       rip24       },
{ 0x31, Z80_ld,     atHL,       rIY         },
{ 0x32, Z80_ld,     rHL,        rHL         },
{ 0x33, Z80_ld,     rIY,        atHL        },
{ 0x34, Z80_inc,    iy8                     },
{ 0x35, Z80_dec,    iy8                     },
{ 0x36, Z80_ld,     iy8,        imm8        },
{ 0x26, Z80_ld,     rIYU,       imm8        },
{ 0x37, Z80_ld,     rIY,        rHL         },
{ 0x38, Z80_jr,     ccC,        rip24       },
{ 0x39, Z80_add,    rIY,        rSP         },
{ 0x3B, Z80_ld,     rHL,        rIY         },
{ 0x3C, Z80_ld,     atBC,       rHL         },
{ 0x3D, Z80_ld,     atDE,       rHL         },
{ 0x3E, Z80_swap,   rIY                     },
{ 0x3F, Z80_ld,     atHL,       rHL         },
{ 0x44, Z80_ld,     rB,         rIYU        },
{ 0x45, Z80_ld,     rB,         rIYL        },
{ 0x46, Z80_ld,     rB,         iy8         },
{ 0x4C, Z80_ld,     rC,         rIYU        },
{ 0x4D, Z80_ld,     rC,         rIYL        },
{ 0x4E, Z80_ld,     rC,         iy8         },
{ 0x54, Z80_ld,     rD,         rIYU        },
{ 0x55, Z80_ld,     rD,         rIYL        },
{ 0x56, Z80_ld,     rD,         iy8         },
{ 0x5C, Z80_ld,     rE,         rIYU        },
{ 0x5D, Z80_ld,     rE,         rIYL        },
{ 0x5E, Z80_ld,     rE,         iy8         },
{ 0x60, Z80_ld,     rIYU,       rB          },
{ 0x61, Z80_ld,     rIYU,       rC          },
{ 0x62, Z80_ld,     rIYU,       rD          },
{ 0x63, Z80_ld,     rIYU,       rE          },
{ 0x64, Z80_ld,     rIYU,       rIYU        },
{ 0x65, Z80_ld,     rIYU,       rIYL        },
{ 0x66, Z80_ld,     rH,         iy8         },
{ 0x67, Z80_ld,     rIYU,       rA          },
{ 0x68, Z80_ld,     rIYL,       rB          },
{ 0x69, Z80_ld,     rIYL,       rC          },
{ 0x6A, Z80_ld,     rIYL,       rD          },
{ 0x6B, Z80_ld,     rIYL,       rE          },
{ 0x6C, Z80_ld,     rIYL,       rIYU        },
{ 0x6D, Z80_ld,     rIYL,       rIYL        },
{ 0x6E, Z80_ld,     rL,         iy8         },
{ 0x6F, Z80_ld,     rIYL,       rA          },
{ 0x70, Z80_ld,     iy8,        rB          },
{ 0x71, Z80_ld,     iy8,        rC          },
{ 0x72, Z80_ld,     iy8,        rD          },
{ 0x73, Z80_ld,     iy8,        rE          },
{ 0x74, Z80_ld,     iy8,        rH          },
{ 0x75, Z80_ld,     iy8,        rL          },
{ 0x77, Z80_ld,     iy8,        rA          },
{ 0x79, Z80_outw,   atC,        imm16       },
{ 0x7C, Z80_ld,     rA,         rIYU        },
{ 0x7D, Z80_ld,     rA,         rIYL        },
{ 0x7E, Z80_ld,     rA,         iy8         },
{ 0x84, Z80_add,    rA,         rIYU        },
{ 0x85, Z80_add,    rA,         rIYL        },
{ 0x86, Z80_add,    rA,         iy8         },
{ 0x87, Z80_addw,   rHL,        rIY         },
{ 0x8C, Z80_adc,    rA,         rIYU        },
{ 0x8D, Z80_adc,    rA,         rIYL        },
{ 0x8E, Z80_adc,    rA,         iy8         },
{ 0x8F, Z80_adcw,   rHL,        rIY         },
{ 0x8F, Z80_adcw,   rIY                     },
{ 0x94, Z80_sub,    rA,         rIYU        },
{ 0x95, Z80_sub,    rA,         rIYL        },
{ 0x96, Z80_sub,    rA,         iy8         },
{ 0x97, Z80_subw,   rHL,        rIY         },
{ 0x9C, Z80_sbc,    rA,         rIYU        },
{ 0x9D, Z80_sbc,    rA,         rIYL        },
{ 0x9E, Z80_sbc,    rA,         iy8         },
{ 0x9F, Z80_sbcw,   rHL,        rIY         },
{ 0xA4, Z80_and,    rA,         rIYU        },
{ 0xA5, Z80_and,    rA,         rIYL        },
{ 0xA6, Z80_and,    rA,         iy8         },
{ 0xA7, Z80_andw,   rHL,        rIY         },
{ 0xAC, Z80_xor,    rA,         rIYU        },
{ 0xAD, Z80_xor,    rA,         rIYL        },
{ 0xAE, Z80_xor,    rA,         iy8         },
{ 0xAF, Z80_xorw,   rHL,        rIY         },
{ 0xB4, Z80_or,     rA,         rIYU        },
{ 0xB5, Z80_or,     rA,         rIYL        },
{ 0xB6, Z80_or,     rA,         iy8         },
{ 0xB7, Z80_orw,    rHL,        rIY         },
{ 0xBC, Z80_cp,     rA,         rIYU        },
{ 0xBD, Z80_cp,     rA,         rIYL        },
{ 0xBE, Z80_cp,     rA,         iy8         },
{ 0xBF, Z80_cpw,    rHL,        rIY         },
{ 0xC0, Z80_ddir,   rLW                     },
{ 0xC1, Z80_ddir,   rIB,        rLW         },
{ 0xC2, Z80_ddir,   rIW,        rLW         },
{ 0xC3, Z80_ddir,   rIW                     },
{ 0xC4, Z80_calr,   ccNZ,       rip24       },
{ 0xC6, Z80_addw,   iy8                     },
{ 0xC6, Z80_addw,   rHL,        iy8         },
{ 0xCC, Z80_calr,   ccZ,        rip24       },
{ 0xCD, Z80_calr,   rip24                   },
{ 0xCE, Z80_adcw,   rHL,        iy8         },
{ 0xD0, Z80_ldctl,  rA,         rYSR        },
{ 0xD3, Z80_outaw,  imm16,      rHL         },
{ 0xD4, Z80_calr,   ccNC,       rip24       },
{ 0xD6, Z80_subw,   rHL,        iy8         },
{ 0xD8, Z80_ldctl,  rYSR,       rA          },
{ 0xD9, Z80_exxy,                           },
{ 0xDA, Z80_ldctl,  rYSR,       imm8        },
{ 0xDB, Z80_inaw,   rHL,        imm16       },
{ 0xDC, Z80_calr,   ccC,        rip24       },
{ 0xDE, Z80_sbcw,   rHL,        iy8         },
{ 0xE1, Z80_pop,    rIY                     },
{ 0xE3, Z80_ex,     atSP,       rIY         },
{ 0xE4, Z80_calr,   ccPO,       rip24       },
{ 0xE5, Z80_push,   rIY                     },
{ 0xE6, Z80_andw,   rHL,        iy8         },
{ 0xE9, Z80_jp,     atIY                    },
{ 0xEC, Z80_calr,   ccPE,       rip24       },
{ 0xEE, Z80_xorw,   rHL,        iy8         },
{ 0xF4, Z80_calr,   ccP,        rip24       },
{ 0xF5, Z80_push,   imm16                   },
{ 0xF6, Z80_orw,    rHL,        iy8         },
{ 0xF7, Z80_setc,   rXM                     },
{ 0xF9, Z80_ld,     rSP,        rIY         },
{ 0xFC, Z80_calr,   ccM,        rip24       },
{ 0xFE, Z80_cpw,    rHL,        iy8         },
{ 0x00, 0 },
};

//the next byte after FDBC is in saved_value
static insndesc_t cmdsFDCB[] = {
{ 0x02, Z80_rlcw,   iys                     },
{ 0x03, Z80_ld,     rBC,        iys         },
{ 0x06, Z80_rlc,    iys                     },
{ 0x0A, Z80_rrcw,   iys                     },
{ 0x0B, Z80_ld,     iys,        rBC         },
{ 0x0E, Z80_rrc,    iys                     },
{ 0x12, Z80_rlw,    iys                     },
{ 0x13, Z80_ld,     rDE,        iys         },
{ 0x16, Z80_rl,     iys                     },
{ 0x1A, Z80_rrw,    iys                     },
{ 0x1B, Z80_ld,     iys,        rDE         },
{ 0x1E, Z80_rr,     iys                     },
{ 0x21, Z80_ld,     rIY,        sps         },
{ 0x22, Z80_slaw,   iys                     },
{ 0x23, Z80_ld,     rIX,        iys         },
{ 0x26, Z80_sla,    iys                     },
{ 0x29, Z80_ld,     sps,        rIY         },
{ 0x2A, Z80_sraw,   iys                     },
{ 0x2B, Z80_ld,     iys,        rIX         },
{ 0x2E, Z80_sra,    iys                     },
{ 0x33, Z80_ld,     rHL,        iys         },
{ 0x3A, Z80_srlw,   iys                     },
{ 0x3B, Z80_ld,     iys,        rHL         },
{ 0x3E, Z80_srl,    iys                     },
{ 0x46, Z80_bit,    c0,         iys         },
{ 0x4E, Z80_bit,    c1,         iys         },
{ 0x56, Z80_bit,    c2,         iys         },
{ 0x5E, Z80_bit,    c3,         iys         },
{ 0x66, Z80_bit,    c4,         iys         },
{ 0x6E, Z80_bit,    c5,         iys         },
{ 0x76, Z80_bit,    c6,         iys         },
{ 0x7E, Z80_bit,    c7,         iys         },
{ 0x86, Z80_res,    c0,         iys         },
{ 0x8E, Z80_res,    c1,         iys         },
{ 0x92, Z80_multw,  iys                     },
{ 0x92, Z80_multw,  rHL,        iys         },
{ 0x96, Z80_res,    c2,         iys         },
{ 0x9A, Z80_multuw, iys                     },
{ 0x9A, Z80_multuw, rHL,        iys         },
{ 0x9E, Z80_res,    c3,         iys         },
{ 0xA6, Z80_res,    c4,         iys         },
{ 0xAE, Z80_res,    c5,         iys         },
{ 0xB6, Z80_res,    c6,         iys         },
{ 0xBA, Z80_divuw,  iys                     },
{ 0xBA, Z80_divuw,  rHL,        iys         },
{ 0xBE, Z80_res,    c7,         iys         },
{ 0xC6, Z80_set,    c0,         iys         },
{ 0xCE, Z80_set,    c1,         iys         },
{ 0xD6, Z80_set,    c2,         iys         },
{ 0xDE, Z80_set,    c3,         iys         },
{ 0xE6, Z80_set,    c4,         iys         },
{ 0xEE, Z80_set,    c5,         iys         },
{ 0xF6, Z80_set,    c6,         iys         },
{ 0xFE, Z80_set,    c7,         iys         },
{ 0x00, 0 },
};

static insndesc_t cmdsED[] = {
{ 0x00, Z80_in0,    rB,         imm8        },
{ 0x01, Z80_out0,   imm8,       rB          },
{ 0x02, Z80_ld,     rBC,        rBC         },
{ 0x03, Z80_ex,     rBC,        rIX         },
{ 0x04, Z80_tst,    rB                      },
{ 0x05, Z80_ex,     rBC,        rDE         },
{ 0x06, Z80_ldw,    atBC,       imm16       },
{ 0x07, Z80_ex,     rA,         rB          },
{ 0x08, Z80_in0,    rC,         imm8        },
{ 0x09, Z80_out0,   imm8,       rC          },
{ 0x0B, Z80_ex,     rBC,        rIY         },
{ 0x0C, Z80_tst,    rC                      },
{ 0x0D, Z80_ex,     rBC,        rHL         },
{ 0x0E, Z80_swap,   rBC                     },
{ 0x0F, Z80_ex,     rA,         rC          },
{ 0x10, Z80_in0,    rD,         imm8        },
{ 0x11, Z80_out0,   imm8,       rD          },
{ 0x12, Z80_ld,     rDE,        rBC         },
{ 0x13, Z80_ex,     rDE,        rIX         },
{ 0x14, Z80_tst,    rD                      },
{ 0x16, Z80_ldw,    atDE,       imm16       },
{ 0x17, Z80_ex,     rA,         rD          },
{ 0x18, Z80_in0,    rE,         imm8        },
{ 0x19, Z80_out0,   imm8,       rE          },
{ 0x1B, Z80_ex,     rDE,        rIY         },
{ 0x1C, Z80_tst,    rE                      },
{ 0x1E, Z80_swap,   rDE                     },
{ 0x1F, Z80_ex,     rA,         rE          },
{ 0x20, Z80_in0,    rH,         imm8        },
{ 0x21, Z80_out0,   imm8,       rH          },
{ 0x24, Z80_tst,    rH                      },
{ 0x27, Z80_ex,     rA,         rH          },
{ 0x28, Z80_in0,    rL,         imm8        },
{ 0x29, Z80_out0,   imm8,       rL          },
{ 0x2B, Z80_ex,     rIX,        rIY         },
{ 0x2C, Z80_tst,    rL                      },
{ 0x2F, Z80_ex,     rA,         rL          },
{ 0x30, Z80_in0,    imm8                    },
{ 0x32, Z80_ld,     rHL,        rBC         },
{ 0x33, Z80_ex,     rHL,        rIX         },
{ 0x34, Z80_tst,    atHL                    },
{ 0x36, Z80_ldw,    atHL,       imm16       },
{ 0x37, Z80_ex,     rA,         atHL        },
{ 0x38, Z80_in0,    rA,         imm8        },
{ 0x39, Z80_out0,   imm8,       rA          },
{ 0x3B, Z80_ex,     rHL,        rIY         },
{ 0x3C, Z80_tst,    rA                      },
{ 0x3E, Z80_swap,   rHL                     },
{ 0x3F, Z80_ex,     rA,         rA          },
{ 0x40, Z80_in,     rB,         atC         },
{ 0x41, Z80_out,    atC,        rB          },
{ 0x42, Z80_sbc,    rHL,        rBC         },
{ 0x43, Z80_ld,     mem16,      rBC         },
{ 0x44, Z80_neg,    rA                      },
{ 0x45, Z80_retn,                           },
{ 0x46, Z80_im,     c0                      },
{ 0x47, Z80_ld,     rI,         rA          },
{ 0x48, Z80_in,     rC,         atC         },
{ 0x49, Z80_out,    atC,        rC          },
{ 0x4A, Z80_adc,    rHL,        rBC         },
{ 0x4B, Z80_ld,     rBC,        mem16       },
{ 0x4C, Z80_mlt,    rBC                     },
{ 0x4D, Z80_reti,                           },
{ 0x4E, Z80_im,     c3                      },
{ 0x4F, Z80_ld,     rR,         rA          },
{ 0x50, Z80_in,     rD,         atC         },
{ 0x51, Z80_out,    atC,        rD          },
{ 0x52, Z80_sbc,    rHL,        rDE         },
{ 0x53, Z80_ld,     mem16,      rDE         },
{ 0x54, Z80_negw,   rHL                     },
{ 0x56, Z80_im,     c1                      },
{ 0x57, Z80_ld,     rA,         rI          },
{ 0x58, Z80_in,     rE,         atC         },
{ 0x59, Z80_out,    atC,        rE          },
{ 0x5A, Z80_adc,    rHL,        rDE         },
{ 0x5B, Z80_ld,     rDE,        mem16       },
{ 0x5C, Z80_mlt,    rDE                     },
{ 0x5E, Z80_im,     c2                      },
{ 0x5F, Z80_ld,     rA,         rR          },
{ 0x60, Z80_in,     rH,         atC         },
{ 0x61, Z80_out,    atC,        rH          },
{ 0x62, Z80_sbc,    rHL,        rHL         },
{ 0x64, Z80_tst,    imm8                    },
{ 0x65, Z80_exts,   rA                      },
{ 0x67, Z80_rrd,                            },
{ 0x68, Z80_in,     rL,         atC         },
{ 0x69, Z80_out,    atC,        rL          },
{ 0x6A, Z80_adc,    rHL,        rHL         },
{ 0x6C, Z80_mlt,    rHL                     },
{ 0x6F, Z80_rld,                            },
{ 0x71, Z80_out,    atC,        imm8        },
{ 0x72, Z80_sbc,    rHL,        rSP         },
{ 0x73, Z80_ld,     mem16,      rSP         },
{ 0x74, Z80_tstio,  imm8                    },
{ 0x75, Z80_extsw,  rHL                     },
{ 0x76, Z80_slp,                            },
{ 0x78, Z80_in,     rA,         atC         },
{ 0x79, Z80_out,    atC,        rA          },
{ 0x7A, Z80_adc,    rHL,        rSP         },
{ 0x7B, Z80_ld,     rSP,        mem16       },
{ 0x7C, Z80_mlt,    rSP                     },
{ 0x82, Z80_add,    rSP,        imm16       },
{ 0x83, Z80_otim,                           },
{ 0x84, Z80_addw,   rHL,        rBC         },
{ 0x85, Z80_addw,   rHL,        rDE         },
{ 0x86, Z80_addw,   rHL,        imm16       },
{ 0x87, Z80_addw,   rHL,        rHL         },
{ 0x8B, Z80_otdm,                           },
{ 0x8C, Z80_adcw,   rHL,        rBC         },
{ 0x8D, Z80_adcw,   rHL,        rDE         },
{ 0x8E, Z80_adcw,   rHL,        imm16       },
{ 0x8F, Z80_adcw,   rHL,        rHL         },
{ 0x92, Z80_sub,    rSP,        imm16       },
{ 0x93, Z80_otimr,                          },
{ 0x94, Z80_subw,   rHL,        rBC         },
{ 0x95, Z80_subw,   rHL,        rDE         },
{ 0x96, Z80_subw,   rHL,        imm16       },
{ 0x97, Z80_subw,   rHL,        rHL         },
{ 0x9B, Z80_otdmr,                          },
{ 0x9C, Z80_sbcw,   rHL,        rBC         },
{ 0x9D, Z80_sbcw,   rHL,        rDE         },
{ 0x9E, Z80_sbcw,   rHL,        imm16       },
{ 0x9F, Z80_sbcw,   rHL,        rHL         },
{ 0xA0, Z80_ldi,                            },
{ 0xA1, Z80_cpi,                            },
{ 0xA2, Z80_ini,                            },
{ 0xA3, Z80_outi,                           },
{ 0xA4, Z80_andw,   rHL,        rBC         },
{ 0xA5, Z80_andw,   rHL,        rDE         },
{ 0xA6, Z80_andw,   rHL,        imm16       },
{ 0xA7, Z80_andw,   rHL,        rHL         },
{ 0xA8, Z80_ldd,                            },
{ 0xA9, Z80_cpd,                            },
{ 0xAA, Z80_ind,                            },
{ 0xAB, Z80_outd,                           },
{ 0xAC, Z80_xorw,   rHL,        rBC         },
{ 0xAD, Z80_xorw,   rHL,        rDE         },
{ 0xAE, Z80_xorw,   rHL,        imm16       },
{ 0xAF, Z80_xorw,   rHL,        rHL         },
{ 0xB0, Z80_ldir,                           },
{ 0xB1, Z80_cpir,                           },
{ 0xB2, Z80_inir,                           },
{ 0xB3, Z80_otir,                           },
{ 0xB4, Z80_orw,    rHL,        rBC         },
{ 0xB5, Z80_orw,    rHL,        rDE         },
{ 0xB6, Z80_orw,    rHL,        imm16       },
{ 0xB7, Z80_orw,    rHL,        rHL         },
{ 0xB8, Z80_lddr,                           },
{ 0xB9, Z80_cpdr,                           },
{ 0xBA, Z80_indr,                           },
{ 0xBB, Z80_otdr,                           },
{ 0xBC, Z80_cpw,    rHL,        rBC         },
{ 0xBD, Z80_cpw,    rHL,        rDE         },
{ 0xBE, Z80_cpw,    rHL,        imm16       },
{ 0xBF, Z80_cpw,    rHL,        rHL         },
{ 0xC0, Z80_ldctl,  rHL,        rSR         },
{ 0xC1, Z80_pop,    rSR                     },
{ 0xC4, Z80_calr,   ccNZ,       rip8        },
{ 0xC5, Z80_push,   rSR                     },
{ 0xC6, Z80_add,    rHL,        mem16       },
{ 0xC8, Z80_ldctl,  rSR,        rHL         },
{ 0xCC, Z80_calr,   ccZ,        rip8        },
{ 0xCD, Z80_calr,   rip8                    },
{ 0xCF, Z80_btest,                          },
{ 0xD0, Z80_ldctl,  rA,         rDSR        },
{ 0xD3, Z80_outa,   mem16,      rA          },
{ 0xD4, Z80_calr,   ccNC,       rip8        },
{ 0xD6, Z80_sub,    rHL,        mem16       },
{ 0xD8, Z80_ldctl,  rDSR,       rA          },
{ 0xD9, Z80_exall,                          },
{ 0xDA, Z80_ldctl,  rDSR,       imm8        },
{ 0xDB, Z80_ina,    rA,         mem16       },
{ 0xDC, Z80_calr,   ccC,        rip8        },
{ 0xE0, Z80_ldiw,                           },
{ 0xE2, Z80_iniw,                           },
{ 0xE3, Z80_outiw,                          },
{ 0xE4, Z80_calr,   ccPO,       rip8        },
{ 0xE8, Z80_lddw,                           },
{ 0xEA, Z80_indw,                           },
{ 0xEB, Z80_outdw,                          },
{ 0xEC, Z80_calr,   ccPE,       rip8        },
{ 0xF0, Z80_ldirw,                          },
{ 0xF2, Z80_inirw,                          },
{ 0xF3, Z80_otirw,                          },
{ 0xF4, Z80_calr,   ccP,        rip8        },
{ 0xF7, Z80_setc,   rLCK                    },
{ 0xF8, Z80_lddrw,                          },
{ 0xFA, Z80_indrw,                          },
{ 0xFB, Z80_otdrw,                          },
{ 0xFC, Z80_calr,   ccM,        rip8        },
{ 0xFF, Z80_resc,   rLCK                    },
};

static insndesc_t cmdsEDCB[] = {
{ 0x00, Z80_rlcw,   rBC                     },
{ 0x01, Z80_rlcw,   rDE                     },
{ 0x02, Z80_rlcw,   atHL                    },
{ 0x03, Z80_rlcw,   rHL                     },
{ 0x04, Z80_rlcw,   rIX                     },
{ 0x05, Z80_rlcw,   rIY                     },
{ 0x08, Z80_rrcw,   rBC                     },
{ 0x09, Z80_rrcw,   rDE                     },
{ 0x0A, Z80_rrcw,   atHL                    },
{ 0x0B, Z80_rrcw,   rHL                     },
{ 0x0C, Z80_rrcw,   rIX                     },
{ 0x0D, Z80_rrcw,   rIY                     },
{ 0x10, Z80_rlw,    rBC                     },
{ 0x11, Z80_rlw,    rDE                     },
{ 0x12, Z80_rlw,    atHL                    },
{ 0x13, Z80_rlw,    rHL                     },
{ 0x14, Z80_rlw,    rIX                     },
{ 0x15, Z80_rlw,    rIY                     },
{ 0x18, Z80_rrw,    rBC                     },
{ 0x19, Z80_rrw,    rDE                     },
{ 0x1A, Z80_rrw,    atHL                    },
{ 0x1B, Z80_rrw,    rHL                     },
{ 0x1C, Z80_rrw,    rIX                     },
{ 0x1D, Z80_rrw,    rIY                     },
{ 0x20, Z80_slaw,   rBC                     },
{ 0x21, Z80_slaw,   rDE                     },
{ 0x22, Z80_slaw,   atHL                    },
{ 0x23, Z80_slaw,   rHL                     },
{ 0x24, Z80_slaw,   rIX                     },
{ 0x25, Z80_slaw,   rIY                     },
{ 0x28, Z80_sraw,   rBC                     },
{ 0x29, Z80_sraw,   rDE                     },
{ 0x2A, Z80_sraw,   atHL                    },
{ 0x2B, Z80_sraw,   rHL                     },
{ 0x2C, Z80_sraw,   rIX                     },
{ 0x2D, Z80_sraw,   rIY                     },
{ 0x30, Z80_ex,     rBC,        rBC2        },
{ 0x31, Z80_ex,     rDE,        rDE2        },
{ 0x33, Z80_ex,     rHL,        rHL2        },
{ 0x34, Z80_ex,     rIX,        rIX2        },
{ 0x35, Z80_ex,     rIY,        rIY2        },
{ 0x38, Z80_srlw,   rBC                     },
{ 0x39, Z80_srlw,   rDE                     },
{ 0x3A, Z80_srlw,   atHL                    },
{ 0x3B, Z80_srlw,   rHL                     },
{ 0x3C, Z80_srlw,   rIX                     },
{ 0x3D, Z80_srlw,   rIY                     },
{ 0x90, Z80_multw,  rHL,        rBC         },
{ 0x91, Z80_multw,  rHL,        rDE         },
{ 0x93, Z80_multw,  rHL,        rHL         },
{ 0x94, Z80_multw,  rHL,        rIX         },
{ 0x95, Z80_multw,  rHL,        rIY         },
{ 0x97, Z80_multw,  rHL,        imm16       },
{ 0x98, Z80_multuw, rHL,        rBC         },
{ 0x99, Z80_multuw, rHL,        rDE         },
{ 0x9B, Z80_multuw, rHL,        rHL         },
{ 0x9C, Z80_multuw, rHL,        rIX         },
{ 0x9D, Z80_multuw, rHL,        rIY         },
{ 0x9F, Z80_multuw, rHL,        imm16       },
{ 0xB8, Z80_divuw,  rHL,        rBC         },
{ 0xB9, Z80_divuw,  rHL,        rDE         },
{ 0xBB, Z80_divuw,  rHL,        rHL         },
{ 0xBC, Z80_divuw,  rHL,        rIX         },
{ 0xBD, Z80_divuw,  rHL,        rIY         },
{ 0xBF, Z80_divuw,  rHL,        imm16       },
};

//------------------------------------------------------------------------
static uchar saved_value;

static void load_z80_operand(op_t &x, uchar op)
{
  if ( op == 0 ) return;
  switch ( op )
  {
    case rBC:
    case rDE:
    case rHL:
    case rIX:
    case rIY:
    case rBC2:
    case rDE2:
    case rHL2:
    case rIX2:
    case rIY2:
    case rSP:
    case rLW:
    case rIXL:
    case rIXU:
    case rDSR:
    case rXSR:
    case rIYL:
    case rIYU:
    case rYSR:
    case rSR:
    case rIB:
    case rIW:
    case rXM:
    case rLCK:
      x.dtyp = dt_word;
    case rA:
    case rB:
    case rC:
    case rD:
    case rE:
    case rH:
    case rL:
    case rI:
    case rW:
    case rR:
      x.type = o_reg;
      x.reg = op - 1;
      break;

    case atBC:
      x.type = o_phrase;
      x.phrase = R_bc;
      break;
    case atDE:
      x.type = o_phrase;
      x.phrase = R_de;
      break;
    case atHL:
      x.type = o_phrase;
      x.phrase = R_hl;
      break;
    case atSP:
      x.type = o_phrase;
      x.phrase = R_sp;
      break;
    case atIX:
      x.type = o_phrase;
      x.phrase = R_ix;
      break;
    case atIY:
      x.type = o_phrase;
      x.phrase = R_iy;
      break;
    case atC:
      x.type = o_phrase;
      x.phrase = R_c;
      break;

    case rip8:
      {
        sval_t disp = char(ua_next_byte());
        x.type = o_near;
        x.addr = cmd.ip + cmd.size + disp;
      }
      break;
    case rip16:
      {
        sval_t disp = short(ua_next_word());
        x.type = o_near;
        x.addr = cmd.ip + cmd.size + disp;
      }
      break;
    case rip24:
      {
        sval_t disp = ua_next_word();
        disp |= (sval_t((char)(ua_next_byte())) << 16);
        x.type = o_near;
        x.addr = cmd.ip + cmd.size + disp;
      }
      break;

    case imm8:
      x.type = o_imm;
      x.value = ua_next_byte();
      break;

    case imm16:
      x.type = o_imm;
      x.dtyp = dt_word;
      x.value = ua_next_word();
      break;

    case mem16:
      x.type = o_mem;
      x.addr = ua_next_word();
      break;

    case ix8:
      x.type = o_displ;
      x.phrase = R_ix;
      x.addr = ua_next_byte();
      break;
    case iy8:
      x.type = o_displ;
      x.phrase = R_iy;
      x.addr = ua_next_byte();
      break;
    case ixs:
      x.type = o_displ;
      x.phrase = R_ix;
      x.addr = saved_value;
      break;
    case iys:
      x.type = o_displ;
      x.phrase = R_iy;
      x.addr = saved_value;
      break;
    case sps:
      x.type = o_displ;
      x.phrase = R_sp;
      x.addr = saved_value;
      break;

    case ccNZ:
    case ccZ:
    case ccNC:
    case ccC:
    case ccPO:
    case ccPE:
    case ccP:
    case ccM:
      x.type = o_cond;
      x.Cond = op - ccNZ;
      break;

    case c0:
    case c1:
    case c2:
    case c3:
    case c4:
    case c5:
    case c6:
    case c7:
      x.type = o_imm;
      x.value = op - c0;
      break;

    default:
      warning("%a: interr in z380, code=%x", cmd.ea, code);
  }
}

//------------------------------------------------------------------------
static bool search_map(insndesc_t *map, uchar code)
{
  for ( int i=0; map[i].itype; i++ )
  {
    if ( map[i].code > code ) break;
    if ( map[i].code == code )
    {
      cmd.itype = map[i].itype;
      load_z80_operand(cmd.Op1, map[i].op1);
      load_z80_operand(cmd.Op2, map[i].op2);
      return true;
    }
  }
  return false;
}

//------------------------------------------------------------------------
static bool z380_insns(insndesc_t *map, insndesc_t *cb)
{
  code = ua_next_byte();
  if ( code == 0xCB )
  {
    map = cb;
    saved_value = ua_next_byte();
    code = ua_next_byte();
  }
  return search_map(map, code);
}

//------------------------------------------------------------------------
static bool z380_ED(void)
{
  insndesc_t *map = cmdsED;
  code = ua_next_byte();
  if ( code == 0xCB )
  {
    map = cmdsEDCB;
    code = ua_next_byte();
  }
  return search_map(map, code);
}

//------------------------------------------------------------------------
static void z80_ixcommands(int _isx)
{
  if ( isZ380() )
  {
    if ( _isx )
      z380_insns(cmdsDD, cmdsDDCB);
    else
      z380_insns(cmdsFD, cmdsFDCB);
    return;
  }

  isx = _isx;
  code = ua_next_byte();
  switch ( (code>>4) & 0xF )
  {
    case 0:                             /* 0000???? */
    case 1:                             /* 0001???? */
      if ( (code & 0xF) == 9 )
      {
        cmd.itype = I5_add;
        op_ix(cmd.Op1);
        op_ss(cmd.Op2);
        cmd.Op1.dtyp = dt_word;
        cmd.Op2.dtyp = dt_word;
      }
      break;
    case 2:                             /* 0010???? */
      cmd.Op1.dtyp = dt_word;
      cmd.Op2.dtyp = dt_word;
      (code & 4) ? op_ibyte(cmd.Op1,code & 8) : op_ix(cmd.Op1);
      switch ( code & 0xF )
      {
        case 1:
          cmd.itype = I5_lxi;
          op_nn(cmd.Op2);
          break;
        case 2:
          cmd.itype = I5_mov;
          op_mm(cmd.Op1);
          op_ix(cmd.Op2);
          break;
        case 3:
          cmd.itype = I5_inx;
          break;
        case 4:
        case 0xC:
          cmd.itype = I5_inr;
          break;
        case 5:
        case 0xD:
          cmd.itype = I5_dcr;
          break;
        case 6:
        case 0xE:
          cmd.itype = I5_mvi;
          op_n(cmd.Op2);
          break;
        case 9:
          cmd.itype = I5_add;
          op_ix(cmd.Op2);
          break;
        case 0xA:
          cmd.itype = I5_mov;
          op_mm(cmd.Op2);
          break;
        case 0xB:
          cmd.itype = I5_dcx;
          break;
      }
      break;
    case 3:
      switch ( code & 0xF ) {
        case 4:
          cmd.itype = I5_inr;
          op_xdispl(cmd.Op1);
          break;
        case 5:
          cmd.itype = I5_dcr;
          op_xdispl(cmd.Op1);
          break;
        case 6:
          cmd.itype = I5_mvi;
          op_xdispl(cmd.Op1);
          op_n(cmd.Op2);
          break;
        case 9:
          cmd.itype = I5_add;
          op_ix(cmd.Op1);
          op_ss(cmd.Op2);
          cmd.Op1.dtyp = dt_word;
          cmd.Op2.dtyp = dt_word;
          break;
      }
      break;
    case 4:
    case 5:
      if ( (code & 6) == 4 )
      {
        cmd.itype = I5_mov;
        op_xr1(cmd.Op1);
        op_ibyte(cmd.Op2,code & 1);
        break;
      }
      /* no break */
    case 6:
      if ( (code & 6) == 4 ) break;
      if ( (code & 7) == 6 ) {
        if ( op_xr1(cmd.Op1) ) break;   // mem,mem not allowed
        if ( code == 0x66 ) cmd.Op1.reg = R_h;
        if ( code == 0x6E ) cmd.Op1.reg = R_l;
        op_xdispl(cmd.Op2);
        cmd.itype = I5_mov;
        break;
      }
      if ( (code & 0xF0) == 0x60 ) {
        op_ibyte(cmd.Op1,code & 8);
        op_xr2(cmd.Op2);
        cmd.itype = I5_mov;
      }
      break;
    case 7:
      switch ( code & 0xF ) {
        case 0: case 1: case 2: case 3: case 4: case 5: case 7:
          op_xdispl(cmd.Op1);
          if ( !op_xr2(cmd.Op2) ) cmd.itype = I5_mov;
          if ( code == 0x74 ) cmd.Op2.reg = R_h;
          if ( code == 0x75 ) cmd.Op2.reg = R_l;
          break;
        case 0xE:
          op_xdispl(cmd.Op2);
          op_a(cmd.Op1);
          cmd.itype = I5_mov;           // to show all regs
          break;
        case 0xC:
        case 0xD:
          op_ibyte(cmd.Op2,code & 1);
          op_a(cmd.Op1);
          cmd.itype = I5_mov;           // to show all regs
          break;
      }
      break;
    case 8:
    case 9:
    case 0xA:
    case 0xB:
      if ( (code & 4) == 4 && (code & 7) != 7 )
      {
        int type = (code >> 3) & 7;
        cmd.itype = W [ type ];
        op_a(cmd.Op1);
        ((code & 7) == 6) ? op_xdispl(cmd.Op2)
                          : op_ibyte(cmd.Op2,code & 1);
//      if ( type == 0 || type == 1 || type == 3 ) cmd.Op1.clr_show();
      }
      break;
    case 0xC:
      if ( code == 0xCB ) {
        op_xdispl(cmd.Op2);
        code = ua_next_byte();
        if ( (code & 7) == 6 ) {
          int type = (code>>6) & 3;
          if ( type == 0 ) {
            cmd.itype = CBrols[ (code >> 3) & 7 ];
            op_a(cmd.Op1);
          } else {
            static int brs[] = { I5_null, Z80_bit, Z80_res, Z80_set };
            cmd.itype = brs [ type ];
            cmd.Op1.type = o_imm;
            cmd.Op1.value = (code >> 3) & 7;
          }
        }
      }
      break;
    case 0xE:
      switch ( code & 0xF ) {
        case 1:
          cmd.itype = I5_pop;
          op_ix(cmd.Op1);
          break;
        case 3:
          cmd.itype = Z80_ex;
          cmd.Op1.type   = o_phrase;
          cmd.Op1.phrase = R_sp;
          cmd.Op1.dtyp   = dt_word;
          op_ix(cmd.Op2);
          break;
        case 5:
          cmd.itype = I5_push;
          op_ix(cmd.Op1);
          break;
        case 9:
          cmd.itype = Z80_jp;
          cmd.Op1.type = o_cond;
          cmd.Op1.Cond = oc_not;
          cmd.Op2.type   = o_phrase;
          cmd.Op2.phrase = isx ? R_ix : R_iy;
          cmd.Op2.dtyp   = dt_code;
          break;
        case 0xD:
          code = ua_next_byte();
          switch ( code ) {
            case 0x42:
            case 0x4A:
            case 0x52:
            case 0x5A:
            case 0x62:
            case 0x6A:
            case 0x72:
            case 0x7A:
              cmd.itype = (code & 8) ? I5_adc : Z80_sbc;
              op_ix(cmd.Op1);
              op_ss(cmd.Op2);
              if ( cmd.Op2.reg == R_hl ) op_ix(cmd.Op2);
              break;
            case 0x60:
            case 0x68:
              cmd.itype = I5_in;
              op_ibyte(cmd.Op1,code & 8);
              op_c(cmd.Op2);
              break;
            case 0x61:
            case 0x69:
              cmd.itype = I5_out;
              op_c(cmd.Op1);
              op_ibyte(cmd.Op2,code & 8);
              break;
          }
          break;
      }
    case 0xF:
      if ( code == 0xF9 ) {
        cmd.itype = I5_mov;
        cmd.Op1.type   = o_reg;
        cmd.Op1.phrase = R_sp;
        cmd.Op1.dtyp   = dt_word;
        op_ix(cmd.Op2);
      }
      break;
  }
}


//------------------------------------------------------------------------
static void z80_misc(void)
{
  code = ua_next_byte();
  switch ( code )
  {
    case 0x40:
    case 0x48:
    case 0x50:
    case 0x58:
    case 0x60:
    case 0x68:
    case 0x78:
      cmd.itype = I5_in;
      op_r1(cmd.Op1);
      op_c(cmd.Op2);
      break;
    case 0x41:
    case 0x49:
    case 0x51:
    case 0x59:
    case 0x61:
    case 0x69:
    case 0x79:
      cmd.itype = I5_out;
      op_c(cmd.Op1);
      op_r1(cmd.Op2);
      break;
    case 0x42:
    case 0x4A:
    case 0x52:
    case 0x5A:
    case 0x62:
    case 0x6A:
    case 0x72:
    case 0x7A:
      cmd.itype = (code & 8) ? I5_adc : Z80_sbc;
      cmd.Op1.type  = o_reg;
      cmd.Op1.reg = R_hl;
      cmd.Op1.dtyp  = dt_word;
      op_ss(cmd.Op2);
      break;
    case 0x43:
    case 0x53:
    case 0x73:
      cmd.itype = I5_mov;
      op_mm(cmd.Op1);
      op_ss(cmd.Op2);
      cmd.Op1.dtyp  = dt_word;
      cmd.Op2.dtyp  = dt_word;
      break;
    case 0x44:  cmd.itype = Z80_neg;            break;
    case 0x45:  cmd.itype = Z80_retn;   break;
    case 0x46:
      cmd.itype = Z80_im;
      cmd.Op1.type = o_imm;
      cmd.Op1.value = 0;
      break;
    case 0x47:
      cmd.itype = I5_mov;               // to show all regs
      cmd.Op1.type = o_reg;
      cmd.Op1.reg = R_i;
      op_a(cmd.Op2);
      break;
    case 0x4B:
    case 0x5B:
    case 0x7B:
      cmd.itype = I5_mov;
      op_ss(cmd.Op1);
      op_mm(cmd.Op2);
      cmd.Op1.dtyp  = dt_word;
      cmd.Op2.dtyp  = dt_word;
      break;
    case 0x4D:  cmd.itype = Z80_reti;   break;
    case 0x4F:
      cmd.itype = I5_mov;               // to show all regs
      cmd.Op1.type = o_reg;
      cmd.Op1.reg = R_r;
      op_a(cmd.Op2);
      break;
    case 0x56:
      cmd.itype = Z80_im;
      cmd.Op1.type = o_imm;
      cmd.Op1.value = 1;
      break;
    case 0x5E:
      cmd.itype = Z80_im;
      cmd.Op1.type = o_imm;
      cmd.Op1.value = 2;
      break;
    case 0x57:
      cmd.itype = I5_mov;               // to show all regs
      op_a(cmd.Op1);
      cmd.Op2.type = o_reg;
      cmd.Op2.reg = R_i;
      break;
    case 0x5F:
      cmd.itype = I5_mov;               // to show all regs
      op_a(cmd.Op1);
      cmd.Op2.type = o_reg;
      cmd.Op2.reg = R_r;
      break;
    case 0x67:  cmd.itype = Z80_rrd;    break;
    case 0x6F:  cmd.itype = Z80_rld;    break;

    case 0xA0:  cmd.itype = Z80_ldi;    break;
    case 0xA1:  cmd.itype = Z80_cpi;    break;
    case 0xA2:  cmd.itype = Z80_ini;    break;
    case 0xA3:  cmd.itype = Z80_outi;   break;
    case 0xA8:  cmd.itype = Z80_ldd;    break;
    case 0xA9:  cmd.itype = Z80_cpd;    break;
    case 0xAA:  cmd.itype = Z80_ind;    break;
    case 0xAB:  cmd.itype = Z80_outd;   break;
    case 0xB0:  cmd.itype = Z80_ldir;   break;
    case 0xB1:  cmd.itype = Z80_cpir;   break;
    case 0xB2:  cmd.itype = Z80_inir;   break;
    case 0xB3:  cmd.itype = Z80_otir;   break;
    case 0xB8:  cmd.itype = Z80_lddr;   break;
    case 0xB9:  cmd.itype = Z80_cpdr;   break;
    case 0xBA:  cmd.itype = Z80_indr;   break;
    case 0xBB:  cmd.itype = Z80_otdr;   break;
//
//      HD64180 extensions
//
    case 0x76:  if ( is64180() ) cmd.itype = HD_slp;    break;
    case 0x83:  if ( is64180() ) cmd.itype = HD_otim;   break;
    case 0x93:  if ( is64180() ) cmd.itype = HD_otimr;  break;
    case 0x8B:  if ( is64180() ) cmd.itype = HD_otdm;   break;
    case 0x9B:  if ( is64180() ) cmd.itype = HD_otdmr;  break;
    case 0x64:
      if ( is64180() ) {
        cmd.itype = HD_tst;
        op_n(cmd.Op1);
      }
      break;
    case 0x74:
      if ( is64180() ) {
        cmd.itype = HD_tstio;
        op_n(cmd.Op1);
      }
      break;
    default:
// I did not find an assembler that understands this...
//      if ( (code & 0xC0) == 0x40 && (code & 6) == 0 ) {       // undocumented
//        cmd.itype = (code & 1) ? I5_out : I5_in;
//      op_r1(cmd.Op1);
//      break;
//      }
//--------
      if ( is64180() )
      {
        switch ( code & 0xC0 )
        {
          case 0:
            switch ( code & 7 )
            {
              case 0:
                cmd.itype = HD_in0;
                op_r1(cmd.Op1);
                op_n(cmd.Op2);
                if ( cmd.Op1.type == o_phrase ) op_f(cmd.Op1);
                break;
              case 1:
                cmd.itype = HD_out0;
                op_n(cmd.Op1);
                op_r1(cmd.Op2);
                break;
              case 4:
                cmd.itype = HD_tst;
                op_r1(cmd.Op1);
                break;
            }
            break;
          case 0x40:
            if ( code == 0x70 )
            {
              cmd.itype = I5_in;
              op_f(cmd.Op1);
              op_c(cmd.Op2);
              break;
            }
            if ( (code & 0xF) == 0xC )
            {
              cmd.itype = HD_mlt;
              op_ss(cmd.Op1);
            }
            break;
        }
      }
      break;
  }
}
