Repository URL to install this package:
Version:
9.0~241217-2.fc42 ▾
|
/*
* 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(insn_t &insn, op_t &x)
{
x.type = o_imm;
x.value = insn.get_next_byte();
}
//------------------------------------------------------------------------
inline void op_c(op_t &x)
{
x.type = o_phrase;
x.phrase = R_c;
}
//------------------------------------------------------------------------
static void op_ad(insn_t &insn, op_t &x)
{
x.type = o_near;
x.addr = insn.get_next_word();
}
static void op_a(op_t &x);
static void op_e(insn_t &insn, op_t &x);
static void op_nn(insn_t &insn, op_t &x);
static void op_ad(insn_t &insn, op_t &x);
static void op_n(insn_t &insn, op_t &x);
static void op_mm(insn_t &insn, op_t &x);
static const uint16 W [] = { I5_add,I5_adc,I5_sub,I5_sbb,I5_ana,I5_xra,I5_ora,I5_cmp };
static const uint16 Wi [] = { I5_adi,I5_aci,I5_sui,I5_sbi,I5_ani,I5_xri,I5_ori,I5_cpi };
static const uint16 calls[] = { I5_cnz,I5_cz, I5_cnc,I5_cc, I5_cpo,I5_cpe,I5_cp, I5_cm };
static const uint16 jumps[] = { I5_jnz,I5_jz, I5_jnc,I5_jc, I5_jpo,I5_jpe,I5_jp, I5_jm };
static const uint16 rets [] = { I5_rnz,I5_rz, I5_rnc,I5_rc, I5_rpo,I5_rpe,I5_rp, I5_rm };
static const uint16 rols [] = { I5_rlc,I5_rrc,I5_ral,I5_rar,I5_daa,I5_cma,I5_stc,I5_cmc };
static const uint16 CBrols[]= { Z80_rlc,Z80_rrc,Z80_rl,Z80_rr,Z80_sla,Z80_sra,Z80_srr,Z80_srl };
static const uint16 Zrols[] = { Z80_rlca,Z80_rrca,Z80_rla,Z80_rra,I5_daa,Z80_cpl,Z80_scf,Z80_ccf };
//----------------------------------------------------------------------
static void ConvertToFunny(insn_t &insn)
{
switch ( insn.itype )
{
case I5_mov:
insn.Op1.set_shown();
insn.Op2.set_shown();
if ( insn.Op1.type == o_reg && insn.Op2.type == o_mem )
{
switch ( insn.Op1.reg )
{
case R_bc:
insn.itype = A80_lbcd;
insn.Op1.clr_shown();
break;
case R_de:
insn.itype = A80_lded;
insn.Op1.clr_shown();
break;
case R_sp:
insn.itype = A80_lspd;
insn.Op1.clr_shown();
break;
case R_ix:
insn.itype = A80_lixd;
insn.Op1.clr_shown();
break;
case R_iy:
insn.itype = A80_liyd;
insn.Op1.clr_shown();
break;
}
}
if ( insn.Op1.type == o_mem && insn.Op2.type == o_reg )
{
switch ( insn.Op2.reg )
{
case R_bc:
insn.itype = A80_sbcd;
insn.Op2.clr_shown();
break;
case R_de:
insn.itype = A80_sded;
insn.Op2.clr_shown();
break;
case R_sp:
insn.itype = A80_sspd;
insn.Op2.clr_shown();
break;
case R_ix:
insn.itype = A80_sixd;
insn.Op2.clr_shown();
break;
case R_iy:
insn.itype = A80_siyd;
insn.Op2.clr_shown();
break;
}
}
if ( insn.Op1.type == o_reg && insn.Op2.type == o_reg )
{
switch ( insn.Op1.reg )
{
case R_sp:
if ( insn.Op2.reg == R_ix )
{
insn.Op1.clr_shown();
insn.Op2.clr_shown();
insn.itype = A80_spix;
}
if ( insn.Op2.reg == R_iy )
{
insn.Op1.clr_shown();
insn.Op2.clr_shown();
insn.itype = A80_spiy;
}
break;
case R_r:
insn.itype = A80_mvra;
insn.Op1.clr_shown();
insn.Op2.clr_shown();
break;
case R_i:
insn.itype = A80_mvia;
insn.Op1.clr_shown();
insn.Op2.clr_shown();
break;
case R_a:
if ( insn.Op2.reg == R_r )
{
insn.itype = A80_mvar;
insn.Op1.clr_shown();
insn.Op2.clr_shown();
}
if ( insn.Op2.reg == R_i )
{
insn.itype = A80_mvai;
insn.Op1.clr_shown();
insn.Op2.clr_shown();
}
break;
}
}
break; /* mov */
case Z80_jp:
if ( insn.Op2.type == o_phrase && insn.Op2.phrase == R_ix )
{
insn.itype = A80_pcix;
insn.Op2.clr_shown();
break;
}
if ( insn.Op2.type == o_phrase && insn.Op2.phrase == R_iy )
{
insn.itype = A80_pciy;
insn.Op2.clr_shown();
break;
}
break; /* jp */
case Z80_ex:
insn.Op1.clr_shown();
insn.Op2.clr_shown();
if ( insn.Op2.reg == R_ix )
insn.itype = A80_xtix;
if ( insn.Op2.reg == R_iy )
insn.itype = A80_xtiy;
break; /* ex */
case I5_in:
if ( insn.Op2.type == o_phrase && insn.Op2.reg == R_c )
{
insn.itype = Z80_inp;
insn.Op2.clr_shown();
}
break;
case I5_out:
if ( insn.Op1.type == o_phrase && insn.Op1.reg == R_c )
{
insn.itype = Z80_outp;
insn.Op1.clr_shown();
}
break;
case Z80_cpl:
insn.itype = I5_cma;
break;
case Z80_scf:
insn.itype = I5_stc;
break;
case Z80_ccf:
insn.itype = I5_cmc;
break;
case I5_add:
if ( insn.Op1.type == o_reg && insn.Op1.reg == R_ix )
{
insn.itype = A80_addix;
insn.Op1.clr_shown();
if ( insn.Op2.type == o_reg && insn.Op2.reg == R_ix )
insn.Op2.reg = R_hl;
break;
}
if ( insn.Op1.type == o_reg && insn.Op1.reg == R_iy )
{
insn.itype = A80_addiy;
insn.Op1.clr_shown();
if ( insn.Op2.type == o_reg && insn.Op2.reg == R_iy )
insn.Op2.reg = R_hl;
break;
}
break;
case I5_adc:
if ( insn.Op1.dtype == dt_word && insn.Op1.type == o_reg )
{
insn.itype = A80_addc;
insn.Op1.clr_shown();
if ( insn.Op1.reg == R_ix )
insn.itype = A80_addcix;
if ( insn.Op1.reg == R_iy )
insn.itype = A80_addciy;
if ( insn.Op2.type == o_reg && insn.Op1.reg == insn.Op2.reg )
insn.Op2.reg = R_hl;
}
break;
case Z80_sbc:
if ( insn.Op1.dtype == dt_word && insn.Op1.type == o_reg )
{
insn.itype = A80_subc;
insn.Op1.clr_shown();
if ( insn.Op1.reg == R_ix )
insn.itype = A80_subcix;
if ( insn.Op1.reg == R_iy )
insn.itype = A80_subciy;
if ( insn.Op2.type == o_reg && insn.Op1.reg == insn.Op2.reg )
insn.Op2.reg = R_hl;
}
break;
case Z80_jr:
insn.Op1.clr_shown();
switch ( insn.Op1.Cond )
{
case oc_c: insn.itype = A80_jrc; break;
case oc_nc: insn.itype = A80_jrnc; break;
case oc_z: insn.itype = A80_jrz; break;
case oc_nz: insn.itype = A80_jrnz; break;
}
break;
case Z80_rrca: insn.itype = I5_rrc; break;
case Z80_rlca: insn.itype = I5_rlc; break;
case Z80_rla: insn.itype = I5_ral; break;
case Z80_rl: insn.itype = I5_ral; break;
case Z80_rra: insn.itype = I5_rar; break;
case Z80_rr: insn.itype = I5_rar; break;
case Z80_cpi: insn.itype = A80_cmpi; break;
case Z80_cpd: insn.itype = A80_cmpd; break;
case Z80_outi: insn.itype = A80_oti; break;
case Z80_outd: insn.itype = A80_otd; break;
case Z80_inc: insn.itype = I5_inr; break;
case Z80_dec: insn.itype = I5_dcr; break;
case Z80_im:
if ( insn.Op1.value == 0 )
insn.itype = A80_im0;
else if ( insn.Op1.value == 1 )
insn.itype = A80_im1;
else
insn.itype = A80_im2;
insn.Op1.clr_shown();
break;
}
}
//----------------------------------------------------------------------
void z80_t::ConvertToZ80(insn_t &insn)
{
uint16 cc;
if ( insn.itype < Z80_and )
{
insn.Op1.set_shown();
insn.Op2.set_shown();
}
switch ( insn.itype )
{
case I5_aci:
insn.itype = I5_adc;
break;
case I5_adi:
case I5_dad:
insn.itype = I5_add;
break;
case I5_cmp:
case I5_cpi:
insn.itype = Z80_cp;
if ( !isZ380() )
insn.Op1.clr_shown();
break;
case I5_ana:
case I5_ani:
insn.itype = Z80_and;
if ( !isZ380() )
insn.Op1.clr_shown();
break;
case I5_ora:
case I5_ori:
insn.itype = Z80_or;
if ( !isZ380() )
insn.Op1.clr_shown();
break;
case I5_xra:
case I5_xri:
insn.itype = Z80_xor;
if ( !isZ380() )
insn.Op1.clr_shown();
break;
case I5_sbi:
case I5_sbb:
insn.itype = Z80_sbc;
break;
case I5_sui:
case I5_sub:
insn.itype = I5_sub;
if ( !isZ380() )
insn.Op1.clr_shown();
break;
case I5_dcr:
case I5_dcx:
insn.itype = Z80_dec;
break;
case I5_inr:
case I5_inx:
insn.itype = Z80_inc;
break;
case I5_halt:
insn.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:
insn.itype = Z80_ld;
break;
case I5_xchg:
case I5_xthl:
insn.itype = Z80_ex;
break;
case I5_pchl:
insn.Op1.type = o_phrase;
insn.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:
insn.itype = Z80_ret;
goto zcc;
zjump:
insn.itype = Z80_jp;
goto zcc;
zcall:
insn.itype = Z80_call;
goto zcc;
zcc:
insn.Op2 = insn.Op1;
insn.Op2.n = 1;
insn.Op1.type = o_cond;
insn.Op1.Cond = cc;
break;
}
}
//----------------------------------------------------------------------
static bool is_gameboy_insn(const insn_t &insn)
{
switch ( insn.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 GB_ldh:
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 GB_stop:
case Z80_sub:
case Z80_swap:
case Z80_xor:
break;
default:
return false;
}
return true;
}
//----------------------------------------------------------------------
static void swap_operands(insn_t &insn)
{
op_t op = insn.Op1;
insn.Op1 = insn.Op2;
insn.Op2 = op;
}
//----------------------------------------------------------------------
int z80_t::i5_ana(insn_t *_insn)
{
insn_t &insn = *_insn;
insn.Op1.dtype = dt_byte;
insn.Op2.dtype = dt_byte;
insn.itype = I5_null;
code = insn.get_next_byte();
switch ( code & 0xC0 )
{
case 0x00:
switch ( code & 0xF )
{
case 0:
case 8:
{
int sub = ( code >> 3 ) & 7;
switch ( sub )
{
case 0:
insn.itype = I5_nop;
break;
case 1: // 08
if ( isGB() ) // 08 bb aa LD ($aabb),SP
{
insn.itype = Z80_ld;
op_mm(insn, insn.Op1);
insn.Op1.dtype = dt_word;
insn.Op2.type = o_reg;
insn.Op2.reg = R_sp;
}
else if ( isZ80() )
{
insn.itype = Z80_ex;
insn.Op1.type = o_reg;
insn.Op1.reg = R_af;
insn.Op2.type = o_reg;
insn.Op2.reg = R_af2;
}
else
{
insn.itype = I5_dsub; // undoc
}
break;
case 2: // 10
if ( isGB() ) // 10 00 STOP
{
if ( insn.get_next_byte() )
return 0;
insn.itype = GB_stop;
}
else if ( isZ80() )
{
insn.itype = Z80_djnz;
op_e(insn, insn.Op1);
}
else
{
insn.itype = I5_arhl; // undoc
}
break;
case 3: // 18
if ( isZ80() )
{
Z80_COMMON:
static const uint16 conds[] = { 0,1,2,oc_not,oc_nz,oc_z,oc_nc,oc_c };
insn.Op1.Cond = conds[sub];
insn.itype = Z80_jr;
insn.Op1.type = o_cond;
op_e(insn, insn.Op2);
break;
}
insn.itype = I5_rdel; // undoc
break;
case 4: // 20
if ( isZ80() )
goto Z80_COMMON;
insn.itype = I5_rim;
break;
case 5: // 28
if ( isZ80() )
goto Z80_COMMON;
insn.itype = I5_ldhi; // undoc
GetImm(insn, insn.Op1);
break;
case 6: // 30
if ( isZ80() )
goto Z80_COMMON;
insn.itype = I5_sim;
break;
case 7: // 38
if ( isZ80() )
goto Z80_COMMON;
insn.itype = I5_ldsi;
GetImm(insn, insn.Op1);
break;
}
}
break;
case 1:
insn.itype = I5_lxi;
op_ss(insn.Op1);
op_nn(insn, insn.Op2);
break;
case 9:
insn.itype = I5_dad;
insn.Op1.reg = R_hl;
insn.Op1.dtype = dt_word;
insn.Op1.type = o_reg;
insn.Op1.clr_shown();
op_ss(insn.Op2);
break;
case 0xA:
if ( (code & 0x20) == 0 )
{
insn.itype = I5_ldax;
insn.Op2.type = o_phrase;
insn.Op2.phrase = R_bc + ((code >> 4) & 1);
op_a(insn.Op1);
}
else
{
if ( isGB() )
{
insn.itype = (code & 0x10) ? Z80_ldd : Z80_ldi;
insn.Op1.type = o_reg;
insn.Op1.reg = R_a;
insn.Op2.type = o_phrase;
insn.Op2.phrase = R_hl;
break;
}
insn.Op1.type = o_reg;
if ( (code & 0x10) == 0 )
{
insn.itype = I5_lhld;
insn.Op1.dtype = dt_word;
insn.Op2.dtype = dt_word;
insn.Op1.reg = R_hl;
}
else
{
insn.itype = I5_lda;
insn.Op1.reg = R_a;
}
op_mm(insn, insn.Op2);
}
insn.Op1.clr_shown();
break;
case 2:
if ( (code & 0x20) == 0 )
{
insn.itype = I5_stax;
insn.Op1.type = o_phrase;
insn.Op1.phrase = R_bc + ((code >> 4) & 1);
op_a(insn.Op2);
}
else
{
if ( isGB() )
{
insn.itype = (code & 0x10) ? Z80_ldd : Z80_ldi;
insn.Op1.type = o_phrase;
insn.Op1.phrase = R_hl;
insn.Op2.type = o_reg;
insn.Op2.reg = R_a;
break;
}
insn.Op2.type = o_reg;
if ( (code & 0x10) == 0 )
{
insn.itype = I5_shld;
insn.Op1.dtype = dt_word;
insn.Op2.dtype = dt_word;
insn.Op2.reg = R_hl;
}
else
{
insn.itype = I5_sta;
insn.Op2.reg = R_a;
}
op_mm(insn, insn.Op1);
}
insn.Op2.clr_shown();
break;
case 3:
insn.itype = I5_inx;
op_ss(insn.Op1);
break;
case 0xB:
insn.itype = I5_dcx;
op_ss(insn.Op1);
break;
case 4:
case 0xC:
insn.itype = I5_inr;
op_r1(insn.Op1);
break;
case 5:
case 0xD:
insn.itype = I5_dcr;
op_r1(insn.Op1);
break;
case 6:
case 0xE:
insn.itype = I5_mvi;
op_r1(insn.Op1);
op_n (insn, insn.Op2);
break;
case 7:
case 0xF:
insn.itype = (isZ80() ? Zrols : rols)[ (code >> 3) & 7 ];
break;
}
break;
case 0x40:
insn.itype = I5_halt;
if ( code != 0x76 )
{
insn.itype = I5_mov;
op_r1(insn.Op1);
op_r2(insn.Op2);
}
break;
case 0x80:
op_r2(insn.Op2);
common:
insn.Op1.type = o_reg;
insn.Op1.reg = R_a;
insn.itype = (insn.Op2.type == o_imm ? Wi : W)[ (code >> 3) & 7 ];
insn.Op1.clr_shown();
break;
case 0xC0: /* 11?????? */
switch ( code & 0xF )
{
case 0x0:
case 0x8: /* 11???000 */
if ( isGB() )
{
switch ( code )
{
case 0xE0:
case 0xF0:
insn.itype = Z80_ld;
insn.Op1.type = o_mem;
insn.Op1.addr = 0xFF00 + insn.get_next_byte();
insn.Op2.type = o_reg;
insn.Op2.reg = R_a;
if ( code & 0x10 )
swap_operands(insn);
break;
case 0xE8:
insn.itype = Z80_add;
insn.Op1.type = o_reg;
insn.Op1.reg = R_sp;
GetImm(insn, insn.Op2);
break;
case 0xF8: // docs say this is "ld hl, sp"
// Daniel Filner <danf@codefrog.cx> says
// this is "ld hl, sp+immbyte"
insn.itype = Z80_ld;
insn.Op1.type = o_reg;
insn.Op1.reg = R_hl;
insn.Op2.type = o_displ;
insn.Op2.phrase = R_sp;
insn.Op2.addr = insn.get_next_byte();
break;
default:
goto RETS;
}
break;
}
RETS:
insn.itype = rets[ (code >> 3) & 7 ];
break;
case 0x2:
case 0xA: /* 11???010 */
if ( isGB() )
{
switch ( code )
{
case 0xE2:
case 0xF2:
insn.itype = Z80_ld;
insn.auxpref |= aux_off16;
op_c(insn.Op1);
insn.Op2.type = o_reg;
insn.Op2.reg = R_a;
if ( code & 0x10 )
swap_operands(insn);
break;
case 0xEA:
case 0xFA:
insn.itype = Z80_ld;
op_mm(insn, insn.Op1);
insn.Op2.type = o_reg;
insn.Op2.reg = R_a;
if ( code & 0x10 )
swap_operands(insn);
break;
default:
goto JUMPS;
}
break;
}
JUMPS:
insn.itype = jumps[ (code >> 3) & 7 ];
op_ad(insn, insn.Op1);
break;
case 0x3:
case 0xB: /* 11???011 */
switch ( ( code >> 3 ) & 7 )
{
case 0: /* 11000011=C3 */
insn.itype = I5_jmp;
op_ad(insn, insn.Op1);
break;
case 1: // 11001011=CB - Z80 extensions
if ( isZ80() )
{
code = insn.get_next_byte();
int fn = (code>>6);
if ( fn == 0 )
{
op_r2(insn.Op1);
insn.itype = CBrols[ (code>>3) & 7 ];
if ( insn.itype == Z80_srr )
{
if ( isZ380() )
{
insn.itype = Z80_ex;
op_r2(insn.Op2);
insn.Op2.reg += R_b2;
}
else if ( isGB() )
{
insn.itype = Z80_swap;
}
}
}
else
{
static const uint16 brs[] = { 0, Z80_bit,Z80_res,Z80_set };
insn.itype = brs[fn];
insn.Op1.type = o_imm;
insn.Op1.value = (code>>3) & 7;
op_r2(insn.Op2);
}
}
else
{
insn.itype = I5_rstv; // undoc
}
break;
case 2: /* 11010011=D3 */
insn.itype = I5_out;
op_a(insn.Op2);
op_n(insn, insn.Op1);
break;
case 3: // DB
insn.itype = I5_in;
op_a(insn.Op1);
op_n(insn, insn.Op2);
break;
case 4: // E3
insn.itype = I5_xthl;
insn.Op1.type = o_phrase;
insn.Op1.reg = R_sp;
insn.Op1.clr_shown();
insn.Op2.type = o_reg;
insn.Op2.reg = R_hl;
insn.Op2.clr_shown();
break;
case 5: // EB
insn.itype = I5_xchg;
insn.Op1.type = o_reg;
insn.Op1.reg = R_de;
insn.Op1.clr_shown();
insn.Op2.type = o_reg;
insn.Op2.reg = R_hl;
insn.Op2.clr_shown();
break;
case 6: // F3
insn.itype = I5_di;
break;
case 7: // FB
insn.itype = I5_ei;
break;
}
break;
case 0x4:
case 0xC: /* 11???100 */
insn.itype = calls[ (code >> 3) & 7 ];
op_ad(insn, insn.Op1);
break;
case 0x1:
case 0x5: // 11????01
insn.itype = (code & 4) ? I5_push : I5_pop;
op_dd(insn.Op1);
break;
case 0x6:
case 0xE: // 11???110
op_n(insn, insn.Op2);
goto common;
case 0x7:
case 0xF: // 11???111
insn.itype = I5_rst;
insn.Op1.type = o_imm;
insn.Op1.value = (code >> 3) & 7;
if ( isZ80() )
{ // workaround for bcb6 bug:
uval_t x = insn.Op1.value;
x <<= 3;
insn.Op1.value = x;
}
break;
case 0x9:
switch ( (code >> 4) & 3 )
{
case 0:
insn.itype = I5_ret; // 11001001 = C9
break;
case 1: // 11011001 = D9
if ( isGB() )
insn.itype = Z80_reti;
else if ( isZ80() )
insn.itype = Z80_exx;
else
insn.itype = I5_shlx; // undoc
break;
case 2:
insn.itype = I5_pchl;
break;
case 3:
insn.itype = I5_sphl;
insn.Op1.type = o_reg;
insn.Op1.reg = R_sp;
insn.Op1.clr_shown();
insn.Op2.type = o_reg;
insn.Op2.reg = R_hl;
insn.Op2.clr_shown();
break;
}
break;
case 0xD: /* 11??1101 */
switch ( (code >> 4) & 3 )
{
case 0:
insn.itype = I5_call;
op_ad(insn, insn.Op1);
break;
case 1: // 11011101 = DD - Z80 extensions
if ( is8085() )
{
insn.itype = I5_jnx5; // undoc
op_ad(insn, insn.Op1);
}
else
{
z80_ixcommands(insn, true);
}
break;
case 2: // 11101101 = ED - Z80 extensions
if ( isGB() )
return 0;
else if ( isZ380() )
z380_ED(insn);
else if ( is8085() )
insn.itype = I5_lhlx; // undoc
else
z80_misc(insn);
break;
case 3: // 11111101 = FD - Z80 extensions
if ( is8085() )
{
insn.itype = I5_jx5; // undoc
op_ad(insn, insn.Op1);
}
else
{
z80_ixcommands(insn, false);
}
break;
}
break;
}
break;
}
if ( insn.itype == I5_null )
return 0;
if ( isZ80() )
{
if ( ash.uflag & UAS_FUNNY )
ConvertToFunny(insn);
else
ConvertToZ80(insn);
if ( isGB() && !is_gameboy_insn(insn) )
return 0;
}
return insn.size;
}
//------------------------------------------------------------------------
void z80_t::op_r1(op_t &x) const
{
uint16 mode = (code >> 3) & 7;
if ( mode == 6 )
{
x.type = o_phrase;
x.phrase = R_hl;
}
else
{
x.type = o_reg;
x.reg = mode;
}
}
//------------------------------------------------------------------------
void z80_t::op_r2(op_t &x) const
{
uint16 mode = code & 7;
if ( mode == 6 )
{
x.type = o_phrase;
x.phrase = R_hl;
}
else
{
x.type = o_reg;
x.reg = mode;
}
}
//------------------------------------------------------------------------
void z80_t::op_ss(op_t &x) const
{
uint16 ss = (code >> 4) & 3;
x.type = o_reg;
x.dtype = dt_word;
x.reg = ss + R_bc;
if ( ss == 3 )
x.reg = R_sp;
}
//------------------------------------------------------------------------
void z80_t::op_dd(op_t &x) const
{
uint16 ss = (code >> 4) & 3;
x.type = o_reg;
x.dtype = dt_word;
x.reg = ss + R_bc;
}
//------------------------------------------------------------------------
static void op_nn(insn_t &insn, op_t &x)
{
x.type = o_imm;
x.dtype = dt_word;
x.value = insn.get_next_word();
}
//------------------------------------------------------------------------
static void op_n(insn_t &insn, op_t &x)
{
x.type = o_imm;
x.value = insn.get_next_byte();
}
//------------------------------------------------------------------------
static void op_e(insn_t &insn, op_t &x)
{
x.type = o_near;
sval_t rel = char(insn.get_next_byte());
x.addr = ushort(insn.ip + insn.size + rel);
}
//------------------------------------------------------------------------
static void op_a(op_t &x)
{
x.type = o_reg;
x.reg = R_a;
x.clr_shown();
}
//------------------------------------------------------------------------
static void op_mm(insn_t &insn, op_t &x)
{
x.type = o_mem;
x.addr = insn.get_next_word();
}
//------------------------------------------------------------------------
static void op_f(op_t &x)
{
x.type = o_reg;
x.dtype = dt_byte;
x.reg = R_f;
}
//------------------------------------------------------------------------
void z80_t::op_xdispl(insn_t &insn, op_t &x) const
{
x.type = o_displ;
x.phrase = isx ? R_ix : R_iy;
x.addr = insn.get_next_byte();
}
//------------------------------------------------------------------------
void z80_t::op_ix(op_t &x) const
{
x.type = o_reg;
x.reg = isx ? R_ix : R_iy;
x.dtype = dt_word;
}
//------------------------------------------------------------------------
void z80_t::op_ibyte(op_t &x, int low) const
{
x.type = o_reg;
x.reg = isx
? (low ? R_xl : R_xh)
: (low ? R_yl : R_yh);
}
//------------------------------------------------------------------------
int z80_t::op_xbytereg(op_t &x, uint16 mode) const
{
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;
}
}
//------------------------------------------------------------------------
int z80_t::op_xr1(op_t &x) const
{
return op_xbytereg(x,(code >> 3) & 7);
}
//------------------------------------------------------------------------
int z80_t::op_xr2(op_t &x) const
{
return op_xbytereg(x,code & 7);
}
//------------------------------------------------------------------------
struct insndesc_t
{
uchar code;
ushort itype; //lint !e958 padding is required to align members
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 const 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 const 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 const 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 const 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 const 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 const 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 },
};
//------------------------------------------------------------------------
void z80_t::load_z80_operand(insn_t &insn, 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.dtype = dt_word;
// fallthrough
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(insn.get_next_byte());
x.type = o_near;
x.addr = insn.ip + insn.size + disp;
}
break;
case rip16:
{
sval_t disp = short(insn.get_next_word());
x.type = o_near;
x.addr = insn.ip + insn.size + disp;
}
break;
case rip24:
{
sval_t disp = insn.get_next_word();
disp |= (sval_t((char)(insn.get_next_byte())) << 16);
x.type = o_near;
x.addr = insn.ip + insn.size + disp;
}
break;
case imm8:
x.type = o_imm;
x.value = insn.get_next_byte();
break;
case imm16:
x.type = o_imm;
x.dtype = dt_word;
x.value = insn.get_next_word();
break;
case mem16:
x.type = o_mem;
x.addr = insn.get_next_word();
break;
case ix8:
x.type = o_displ;
x.phrase = R_ix;
x.addr = insn.get_next_byte();
break;
case iy8:
x.type = o_displ;
x.phrase = R_iy;
x.addr = insn.get_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", insn.ea, code);
}
}
//------------------------------------------------------------------------
bool z80_t::search_map(insn_t &insn, const insndesc_t *map, uchar _code)
{
for ( int i=0; map[i].itype; i++ )
{
if ( map[i].code > _code )
break;
if ( map[i].code == _code )
{
insn.itype = map[i].itype;
load_z80_operand(insn, insn.Op1, map[i].op1);
load_z80_operand(insn, insn.Op2, map[i].op2);
return true;
}
}
return false;
}
//------------------------------------------------------------------------
bool z80_t::z380_insns(insn_t &insn, const insndesc_t *map, const insndesc_t *cb)
{
code = insn.get_next_byte();
if ( code == 0xCB )
{
map = cb;
saved_value = insn.get_next_byte();
code = insn.get_next_byte();
}
return search_map(insn, map, (uchar)code);
}
//------------------------------------------------------------------------
bool z80_t::z380_ED(insn_t &insn)
{
const insndesc_t *map = cmdsED;
code = insn.get_next_byte();
if ( code == 0xCB )
{
map = cmdsEDCB;
code = insn.get_next_byte();
}
return search_map(insn, map, (uchar)code);
}
//------------------------------------------------------------------------
void z80_t::z80_ixcommands(insn_t &insn, bool _isx)
{
if ( isGB() )
return;
if ( isZ380() )
{
if ( _isx )
z380_insns(insn, cmdsDD, cmdsDDCB);
else
z380_insns(insn, cmdsFD, cmdsFDCB);
return;
}
isx = _isx;
code = insn.get_next_byte();
switch ( (code>>4) & 0xF )
{
case 0: /* 0000???? */
case 1: /* 0001???? */
if ( (code & 0xF) == 9 )
{
insn.itype = I5_add;
op_ix(insn.Op1);
op_ss(insn.Op2);
insn.Op1.dtype = dt_word;
insn.Op2.dtype = dt_word;
}
break;
case 2: /* 0010???? */
insn.Op1.dtype = dt_word;
insn.Op2.dtype = dt_word;
(code & 4) ? op_ibyte(insn.Op1,code & 8) : op_ix(insn.Op1);
switch ( code & 0xF )
{
case 1:
insn.itype = I5_lxi;
op_nn(insn, insn.Op2);
break;
case 2:
insn.itype = I5_mov;
op_mm(insn, insn.Op1);
op_ix(insn.Op2);
break;
case 3:
insn.itype = I5_inx;
break;
case 4:
case 0xC:
insn.itype = I5_inr;
break;
case 5:
case 0xD:
insn.itype = I5_dcr;
break;
case 6:
case 0xE:
insn.itype = I5_mvi;
op_n(insn, insn.Op2);
break;
case 9:
insn.itype = I5_add;
op_ix(insn.Op2);
break;
case 0xA:
insn.itype = I5_mov;
op_mm(insn, insn.Op2);
break;
case 0xB:
insn.itype = I5_dcx;
break;
}
break;
case 3:
switch ( code & 0xF )
{
case 4:
insn.itype = I5_inr;
op_xdispl(insn, insn.Op1);
break;
case 5:
insn.itype = I5_dcr;
op_xdispl(insn, insn.Op1);
break;
case 6:
insn.itype = I5_mvi;
op_xdispl(insn, insn.Op1);
op_n(insn, insn.Op2);
break;
case 9:
insn.itype = I5_add;
op_ix(insn.Op1);
op_ss(insn.Op2);
insn.Op1.dtype = dt_word;
insn.Op2.dtype = dt_word;
break;
}
break;
case 4:
case 5:
if ( (code & 6) == 4 )
{
insn.itype = I5_mov;
op_xr1(insn.Op1);
op_ibyte(insn.Op2,code & 1);
break;
}
/* no break */
case 6:
if ( (code & 6) == 4 )
break;
if ( (code & 7) == 6 )
{
if ( op_xr1(insn.Op1) )
break; // mem,mem not allowed
if ( code == 0x66 )
insn.Op1.reg = R_h;
if ( code == 0x6E )
insn.Op1.reg = R_l;
op_xdispl(insn, insn.Op2);
insn.itype = I5_mov;
break;
}
if ( (code & 0xF0) == 0x60 )
{
op_ibyte(insn.Op1,code & 8);
op_xr2(insn.Op2);
insn.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(insn, insn.Op1);
if ( !op_xr2(insn.Op2) )
insn.itype = I5_mov;
if ( code == 0x74 )
insn.Op2.reg = R_h;
if ( code == 0x75 )
insn.Op2.reg = R_l;
break;
case 0xE:
op_xdispl(insn, insn.Op2);
op_a(insn.Op1);
insn.itype = I5_mov; // to show all regs
break;
case 0xC:
case 0xD:
op_ibyte(insn.Op2,code & 1);
op_a(insn.Op1);
insn.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;
insn.itype = W[type];
op_a(insn.Op1);
((code & 7) == 6) ? op_xdispl(insn, insn.Op2)
: op_ibyte(insn.Op2,code & 1);
// if ( type == 0 || type == 1 || type == 3 ) insn.Op1.clr_show();
}
break;
case 0xC:
if ( code == 0xCB )
{
op_xdispl(insn, insn.Op2);
code = insn.get_next_byte();
if ( (code & 7) == 6 )
{
int type = (code>>6) & 3;
if ( type == 0 )
{
insn.itype = CBrols[ (code >> 3) & 7 ];
op_a(insn.Op1);
}
else
{
static const uint16 brs[] = { I5_null, Z80_bit, Z80_res, Z80_set };
insn.itype = brs[type];
insn.Op1.type = o_imm;
insn.Op1.value = (code >> 3) & 7;
}
}
}
break;
case 0xE:
switch ( code & 0xF )
{
case 1:
insn.itype = I5_pop;
op_ix(insn.Op1);
break;
case 3:
insn.itype = Z80_ex;
insn.Op1.type = o_phrase;
insn.Op1.phrase = R_sp;
insn.Op1.dtype = dt_word;
op_ix(insn.Op2);
break;
case 5:
insn.itype = I5_push;
op_ix(insn.Op1);
break;
case 9:
insn.itype = Z80_jp;
insn.Op1.type = o_cond;
insn.Op1.Cond = oc_not;
insn.Op2.type = o_phrase;
insn.Op2.phrase = isx ? R_ix : R_iy;
insn.Op2.dtype = dt_code;
break;
case 0xD:
code = insn.get_next_byte();
switch ( code )
{
case 0x42:
case 0x4A:
case 0x52:
case 0x5A:
case 0x62:
case 0x6A:
case 0x72:
case 0x7A:
insn.itype = (code & 8) ? I5_adc : Z80_sbc;
op_ix(insn.Op1);
op_ss(insn.Op2);
if ( insn.Op2.reg == R_hl )
op_ix(insn.Op2);
break;
case 0x60:
case 0x68:
insn.itype = I5_in;
op_ibyte(insn.Op1,code & 8);
op_c(insn.Op2);
break;
case 0x61:
case 0x69:
insn.itype = I5_out;
op_c(insn.Op1);
op_ibyte(insn.Op2,code & 8);
break;
}
break;
}
// fallthrough
case 0xF:
if ( code == 0xF9 )
{
insn.itype = I5_mov;
insn.Op1.type = o_reg;
insn.Op1.phrase = R_sp;
insn.Op1.dtype = dt_word;
op_ix(insn.Op2);
}
break;
}
}
//------------------------------------------------------------------------
void z80_t::z80_misc(insn_t &insn)
{
code = insn.get_next_byte();
switch ( code )
{
case 0x40:
case 0x48:
case 0x50:
case 0x58:
case 0x60:
case 0x68:
case 0x78:
insn.itype = I5_in;
op_r1(insn.Op1);
op_c(insn.Op2);
break;
case 0x41:
case 0x49:
case 0x51:
case 0x59:
case 0x61:
case 0x69:
case 0x79:
insn.itype = I5_out;
op_c(insn.Op1);
op_r1(insn.Op2);
break;
case 0x42:
case 0x4A:
case 0x52:
case 0x5A:
case 0x62:
case 0x6A:
case 0x72:
case 0x7A:
insn.itype = (code & 8) ? I5_adc : Z80_sbc;
insn.Op1.type = o_reg;
insn.Op1.reg = R_hl;
insn.Op1.dtype = dt_word;
op_ss(insn.Op2);
break;
case 0x43:
case 0x53:
case 0x73:
insn.itype = I5_mov;
op_mm(insn, insn.Op1);
op_ss(insn.Op2);
insn.Op1.dtype = dt_word;
insn.Op2.dtype = dt_word;
break;
case 0x44: insn.itype = Z80_neg; break;
case 0x45: insn.itype = Z80_retn; break;
case 0x46:
insn.itype = Z80_im;
insn.Op1.type = o_imm;
insn.Op1.value = 0;
break;
case 0x47:
insn.itype = I5_mov; // to show all regs
insn.Op1.type = o_reg;
insn.Op1.reg = R_i;
op_a(insn.Op2);
break;
case 0x4B:
case 0x5B:
case 0x7B:
insn.itype = I5_mov;
op_ss(insn.Op1);
op_mm(insn, insn.Op2);
insn.Op1.dtype = dt_word;
insn.Op2.dtype = dt_word;
break;
case 0x4D:
insn.itype = Z80_reti;
break;
case 0x4F:
insn.itype = I5_mov; // to show all regs
insn.Op1.type = o_reg;
insn.Op1.reg = R_r;
op_a(insn.Op2);
break;
case 0x56:
insn.itype = Z80_im;
insn.Op1.type = o_imm;
insn.Op1.value = 1;
break;
case 0x5E:
insn.itype = Z80_im;
insn.Op1.type = o_imm;
insn.Op1.value = 2;
break;
case 0x57:
insn.itype = I5_mov; // to show all regs
op_a(insn.Op1);
insn.Op2.type = o_reg;
insn.Op2.reg = R_i;
break;
case 0x5F:
insn.itype = I5_mov; // to show all regs
op_a(insn.Op1);
insn.Op2.type = o_reg;
insn.Op2.reg = R_r;
break;
case 0x67: insn.itype = Z80_rrd; break;
case 0x6F: insn.itype = Z80_rld; break;
case 0xA0: insn.itype = Z80_ldi; break;
case 0xA1: insn.itype = Z80_cpi; break;
case 0xA2: insn.itype = Z80_ini; break;
case 0xA3: insn.itype = Z80_outi; break;
case 0xA8: insn.itype = Z80_ldd; break;
case 0xA9: insn.itype = Z80_cpd; break;
case 0xAA: insn.itype = Z80_ind; break;
case 0xAB: insn.itype = Z80_outd; break;
case 0xB0: insn.itype = Z80_ldir; break;
case 0xB1: insn.itype = Z80_cpir; break;
case 0xB2: insn.itype = Z80_inir; break;
case 0xB3: insn.itype = Z80_otir; break;
case 0xB8: insn.itype = Z80_lddr; break;
case 0xB9: insn.itype = Z80_cpdr; break;
case 0xBA: insn.itype = Z80_indr; break;
case 0xBB: insn.itype = Z80_otdr; break;
//
// HD64180 extensions
//
case 0x76: if ( is64180() ) insn.itype = HD_slp; break;
case 0x83: if ( is64180() ) insn.itype = HD_otim; break;
case 0x93: if ( is64180() ) insn.itype = HD_otimr; break;
case 0x8B: if ( is64180() ) insn.itype = HD_otdm; break;
case 0x9B: if ( is64180() ) insn.itype = HD_otdmr; break;
case 0x64:
if ( is64180() )
{
insn.itype = HD_tst;
op_n(insn, insn.Op1);
}
break;
case 0x74:
if ( is64180() )
{
insn.itype = HD_tstio;
op_n(insn, insn.Op1);
}
break;
default:
// I did not find an assembler that understands this...
// if ( (code & 0xC0) == 0x40 && (code & 6) == 0 ) // undocumented
// {
// insn.itype = (code & 1) ? I5_out : I5_in;
// op_r1(insn.Op1);
// break;
// }
//--------
if ( is64180() )
{
switch ( code & 0xC0 )
{
case 0:
switch ( code & 7 )
{
case 0:
insn.itype = HD_in0;
op_r1(insn.Op1);
op_n(insn, insn.Op2);
if ( insn.Op1.type == o_phrase )
op_f(insn.Op1);
break;
case 1:
insn.itype = HD_out0;
op_n(insn, insn.Op1);
op_r1(insn.Op2);
break;
case 4:
insn.itype = HD_tst;
op_r1(insn.Op1);
break;
}
break;
case 0x40:
if ( code == 0x70 )
{
insn.itype = I5_in;
op_f(insn.Op1);
op_c(insn.Op2);
break;
}
if ( (code & 0xF) == 0xC )
{
insn.itype = HD_mlt;
op_ss(insn.Op1);
}
break;
}
}
break;
}
}