update to ida 7.6, add builds
This commit is contained in:
2631
idasdk76/module/z80/ana.cpp
Normal file
2631
idasdk76/module/z80/ana.cpp
Normal file
File diff suppressed because it is too large
Load Diff
429
idasdk76/module/z80/emu.cpp
Normal file
429
idasdk76/module/z80/emu.cpp
Normal file
@@ -0,0 +1,429 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Version 3.06
|
||||
* Copyright (c) 1990-96 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* FIDO: 2:5020/209
|
||||
* E-mail: ig@estar.msk.su
|
||||
*
|
||||
*/
|
||||
|
||||
#include "i5.hpp"
|
||||
#include <idd.hpp>
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static void set_immd_bit(const insn_t &insn, int n)
|
||||
{
|
||||
set_immd(insn.ea);
|
||||
if ( !is_defarg(get_flags(insn.ea), n) )
|
||||
{
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case I5_ani:
|
||||
case I5_xri:
|
||||
case I5_ori:
|
||||
case I5_in:
|
||||
case I5_out:
|
||||
case I5_rst:
|
||||
|
||||
case HD_in0:
|
||||
case HD_out0:
|
||||
case HD_tstio:
|
||||
op_num(insn.ea,-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void z80_t::load_operand(const insn_t &insn, const op_t &x)
|
||||
{
|
||||
dref_t xreftype;
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_reg:
|
||||
case o_phrase:
|
||||
default:
|
||||
break;
|
||||
|
||||
case o_imm:
|
||||
xreftype = dr_O;
|
||||
MakeImm:
|
||||
set_immd_bit(insn, x.n);
|
||||
if ( op_adds_xrefs(get_flags(insn.ea), x.n) )
|
||||
insn.add_off_drefs(x, xreftype, 0);
|
||||
break;
|
||||
case o_displ:
|
||||
xreftype = dr_R;
|
||||
goto MakeImm;
|
||||
|
||||
case o_mem:
|
||||
{
|
||||
ea_t ea = map_data_ea(insn, x);
|
||||
insn.add_dref(ea, x.offb, dr_R);
|
||||
insn.create_op_data(ea, x);
|
||||
}
|
||||
break;
|
||||
|
||||
case o_near:
|
||||
{
|
||||
ea_t ea = map_code_ea(insn, x);
|
||||
ea_t segbase = (ea - x.addr) >> 4;
|
||||
ea_t thisseg = insn.cs;
|
||||
int iscall = has_insn_feature(insn.itype,CF_CALL);
|
||||
insn.add_cref(
|
||||
ea,
|
||||
x.offb,
|
||||
iscall ? (segbase == thisseg ? fl_CN : fl_CF)
|
||||
: (segbase == thisseg ? fl_JN : fl_JF));
|
||||
if ( iscall && !func_does_return(ea) )
|
||||
flow = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void save_operand(const insn_t &insn, const op_t &x)
|
||||
{
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_reg:
|
||||
break;
|
||||
case o_mem:
|
||||
{
|
||||
ea_t ea = map_data_ea(insn, x);
|
||||
insn.create_op_data(ea, x);
|
||||
insn.add_dref(ea, x.offb, dr_W);
|
||||
}
|
||||
break;
|
||||
case o_displ:
|
||||
set_immd_bit(insn, x.n);
|
||||
if ( op_adds_xrefs(get_flags(insn.ea), x.n) )
|
||||
insn.add_off_drefs(x, dr_W, OOF_ADDR);
|
||||
case o_phrase:
|
||||
break;
|
||||
default:
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case Z80_in0:
|
||||
case Z80_outaw:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int z80_t::i5_emu(const insn_t &insn)
|
||||
{
|
||||
uint32 Feature = insn.get_canon_feature(ph);
|
||||
flow = ((Feature & CF_STOP) == 0);
|
||||
|
||||
if ( (Feature & CF_USE1) )
|
||||
load_operand(insn, insn.Op1);
|
||||
if ( (Feature & CF_USE2) )
|
||||
load_operand(insn, insn.Op2);
|
||||
|
||||
if ( Feature & CF_JUMP )
|
||||
remember_problem(PR_JUMP, insn.ea);
|
||||
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case I5_mov:
|
||||
case I5_mvi:
|
||||
case Z80_ld:
|
||||
break;
|
||||
case Z80_jp:
|
||||
case Z80_jr: // Z80
|
||||
case Z80_ret: // Z80
|
||||
if ( insn.Op1.Cond != oc_not )
|
||||
break;
|
||||
// no break
|
||||
case I5_jmp:
|
||||
if ( insn.Op2.type == o_phrase )
|
||||
remember_problem(PR_JUMP, insn.ea);
|
||||
// no break
|
||||
case I5_ret:
|
||||
flow = false;
|
||||
break;
|
||||
case I5_rstv:
|
||||
add_cref(insn.ea, map_code_ea(insn, 0x40, 0), fl_CN);
|
||||
break;
|
||||
case I5_rst:
|
||||
{
|
||||
int mul = isZ80() ? 1 : 8;
|
||||
ushort offset = ushort(insn.Op1.value * mul);
|
||||
add_cref(insn.ea, map_code_ea(insn, offset, 0), fl_CN);
|
||||
}
|
||||
case I5_call:
|
||||
case I5_cc:
|
||||
case I5_cnc:
|
||||
case I5_cz:
|
||||
case I5_cnz:
|
||||
case I5_cpe:
|
||||
case I5_cpo:
|
||||
case I5_cp:
|
||||
case I5_cm:
|
||||
case Z80_exx: // Z80
|
||||
// i5_CPUregs.bc.undef();
|
||||
// i5_CPUregs.de.undef();
|
||||
// i5_CPUregs.hl.undef();
|
||||
// i5_CPUregs.af.undef();
|
||||
// i5_CPUregs.ix.undef();
|
||||
// i5_CPUregs.iy.undef();
|
||||
break;
|
||||
default:
|
||||
// R1.undef();
|
||||
// R2.undef();
|
||||
break;
|
||||
}
|
||||
|
||||
if ( Feature & CF_CHG1 )
|
||||
save_operand(insn, insn.Op1);
|
||||
if ( Feature & CF_CHG2 )
|
||||
save_operand(insn, insn.Op2);
|
||||
|
||||
if ( flow )
|
||||
add_cref(insn.ea, insn.ea+insn.size, fl_F);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
sval_t z80_t::named_regval(
|
||||
const char *regname,
|
||||
getreg_t *getreg,
|
||||
const regval_t *rv)
|
||||
{
|
||||
// Get register info.
|
||||
const char *main_regname;
|
||||
bitrange_t bitrange;
|
||||
if ( !get_reg_info(&main_regname, &bitrange, regname) )
|
||||
return 0;
|
||||
|
||||
// Get main register value and apply bitrange.
|
||||
sval_t ret = getreg(main_regname, rv).ival;
|
||||
ret >>= bitrange.bitoff();
|
||||
ret &= (1ULL << bitrange.bitsize()) - 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
sval_t z80_t::regval(const op_t &op, getreg_t *getreg, const regval_t *rv)
|
||||
{
|
||||
// Check for bad register number.
|
||||
if ( op.reg > R_a2 )
|
||||
return 0;
|
||||
return named_regval(ph.reg_names[op.reg], getreg, rv);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool z80_t::check_cond(
|
||||
uint16_t cc,
|
||||
getreg_t *getreg,
|
||||
const regval_t *regvalues)
|
||||
{
|
||||
uint16_t F = named_regval("F", getreg, regvalues);
|
||||
bool C = (F & (1 << 0)) != 0;
|
||||
bool PV = (F & (1 << 2)) != 0;
|
||||
bool Z = (F & (1 << 6)) != 0;
|
||||
bool S = (F & (1 << 7)) != 0;
|
||||
switch ( cc )
|
||||
{
|
||||
case oc_nz: return !Z; // non-zero
|
||||
case oc_z: return Z; // zero
|
||||
case oc_nc: return !C; // no carry
|
||||
case oc_c: return C; // carry
|
||||
case oc_po: return !PV; // parity odd
|
||||
case oc_pe: return PV; // parity even
|
||||
case oc_p: return !S; // sign positive
|
||||
case oc_m: return S; // sign negative
|
||||
case oc_not: return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ea_t z80_t::next_exec_insn(
|
||||
ea_t ea,
|
||||
getreg_t *getreg,
|
||||
const regval_t *regvalues)
|
||||
{
|
||||
// Decode instruction at ea.
|
||||
insn_t insn;
|
||||
if ( decode_insn(&insn, ea) < 1 )
|
||||
return BADADDR;
|
||||
|
||||
// Get next address to be executed.
|
||||
ea_t target = BADADDR;
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case Z80_jp:
|
||||
case Z80_jr:
|
||||
case Z80_call:
|
||||
if ( check_cond(insn.Op1.Cond, getreg, regvalues) )
|
||||
{
|
||||
if ( insn.Op2.type == o_near )
|
||||
target = insn.Op2.addr;
|
||||
else if ( insn.Op2.type == o_phrase )
|
||||
target = regval(insn.Op2, getreg, regvalues);
|
||||
}
|
||||
break;
|
||||
|
||||
case Z80_djnz:
|
||||
{
|
||||
uint8_t B = named_regval("B", getreg, regvalues);
|
||||
if ( (B-1) != 0 )
|
||||
target = insn.Op1.addr;
|
||||
}
|
||||
break;
|
||||
|
||||
case Z80_ret:
|
||||
if ( !check_cond(insn.Op1.Cond, getreg, regvalues) )
|
||||
break;
|
||||
// fallthrough
|
||||
case Z80_reti:
|
||||
case Z80_retn:
|
||||
{
|
||||
uint16_t SP = named_regval("SP", getreg, regvalues);
|
||||
target = get_word(SP);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ea_t z80_t::calc_step_over(ea_t ip) const
|
||||
{
|
||||
insn_t insn;
|
||||
if ( ip == BADADDR || decode_insn(&insn, ip) < 1 )
|
||||
return BADADDR;
|
||||
|
||||
// Allow stepping over call instructions and djnz.
|
||||
bool step_over = is_call_insn(insn)
|
||||
|| insn.itype == Z80_djnz;
|
||||
if ( step_over )
|
||||
return insn.ea + insn.size;
|
||||
|
||||
return BADADDR;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool z80_t::get_operand_info(
|
||||
idd_opinfo_t *opinf,
|
||||
ea_t ea,
|
||||
int n,
|
||||
getreg_t *getreg,
|
||||
const regval_t *regvalues)
|
||||
{
|
||||
// No Z80 instruction has operand number greater than 2.
|
||||
if ( n < 0 || n > 2 )
|
||||
return false;
|
||||
|
||||
// Decode instruction at ea.
|
||||
insn_t insn;
|
||||
if ( decode_insn(&insn, ea) < 1 )
|
||||
return false;
|
||||
|
||||
// Check the instruction features to see if the operand is modified.
|
||||
opinf->modified = has_cf_chg(insn.get_canon_feature(ph), n);
|
||||
|
||||
// Get operand value (possibly an ea).
|
||||
uint64 v = 0;
|
||||
const op_t &op = insn.ops[n];
|
||||
switch ( op.type )
|
||||
{
|
||||
case o_reg:
|
||||
// We use the getreg function (along with regvalues) to retrieve
|
||||
// the value of the register specified in op.reg.
|
||||
v = regval(op, getreg, regvalues);
|
||||
break;
|
||||
case o_mem:
|
||||
case o_near:
|
||||
// Memory addresses are stored in op.addr.
|
||||
opinf->ea = op.addr;
|
||||
break;
|
||||
case o_phrase:
|
||||
// Memory references using register value.
|
||||
opinf->ea = regval(op, getreg, regvalues);
|
||||
break;
|
||||
case o_displ:
|
||||
// Memory references using register and address value.
|
||||
opinf->ea = regval(op, getreg, regvalues) + op.addr;
|
||||
break;
|
||||
case o_imm:
|
||||
// Immediates are stored in op.value.
|
||||
v = op.value;
|
||||
break;
|
||||
case o_cond:
|
||||
// This is just a condition code type (see opcond_t). There is no
|
||||
// meaningful value to return.
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
opinf->value._set_int(v);
|
||||
opinf->value_size = get_dtype_size(op.dtype);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool z80_t::get_reg_info(
|
||||
const char **main_regname,
|
||||
bitrange_t *bitrange,
|
||||
const char *regname)
|
||||
{
|
||||
// Sanity checks.
|
||||
if ( regname == NULL || regname[0] == '\0' )
|
||||
return false;
|
||||
|
||||
static const char *const subregs[][3] =
|
||||
{
|
||||
{ "af", "a", "f" },
|
||||
{ "bc", "b", "c" },
|
||||
{ "de", "d", "e" },
|
||||
{ "hl", "h", "l" },
|
||||
{ "af'", "a'", "f'" },
|
||||
{ "bc'", "b'", "c'" },
|
||||
{ "de'", "d'", "e'" },
|
||||
{ "hl'", "h'", "l'" },
|
||||
{ "ix", NULL, NULL },
|
||||
{ "iy", NULL, NULL },
|
||||
{ "sp", NULL, NULL },
|
||||
{ "pc", NULL, NULL },
|
||||
};
|
||||
|
||||
// Check if we are dealing with paired or single registers and return
|
||||
// the appropriate information.
|
||||
for ( size_t i = 0; i < qnumber(subregs); i++ )
|
||||
{
|
||||
for ( size_t j = 0; j < 3; j++ )
|
||||
{
|
||||
if ( subregs[i][j] == NULL )
|
||||
break;
|
||||
if ( strieq(regname, subregs[i][j]) )
|
||||
{
|
||||
if ( main_regname != NULL )
|
||||
*main_regname = subregs[i][0];
|
||||
if ( bitrange != NULL )
|
||||
{
|
||||
switch ( j )
|
||||
{
|
||||
case 0: *bitrange = bitrange_t(0, 16); break;
|
||||
case 1: *bitrange = bitrange_t(8, 8); break;
|
||||
case 2: *bitrange = bitrange_t(0, 8); break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
230
idasdk76/module/z80/i5.hpp
Normal file
230
idasdk76/module/z80/i5.hpp
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Version 2.06
|
||||
* Copyright (c) 1990-93 by Ilfak Guilfanov. (2:5020/209@fidonet)
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef I5HPP
|
||||
#define I5HPP
|
||||
|
||||
#include "../idaidp.hpp"
|
||||
#include "ins.hpp"
|
||||
#include <diskio.hpp>
|
||||
#include "../iohandler.hpp"
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// debugger functions
|
||||
typedef const regval_t &idaapi getreg_t(const char *name, const regval_t *regvalues);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// customization of insn_t structure:
|
||||
#define o_cond o_idpspec0
|
||||
|
||||
#define Cond reg
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
enum opcond_t // condition code types
|
||||
{
|
||||
oc_nz,
|
||||
oc_z,
|
||||
oc_nc,
|
||||
oc_c,
|
||||
oc_po,
|
||||
oc_pe,
|
||||
oc_p,
|
||||
oc_m,
|
||||
oc_not
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
#define _PT_64180 0x01 // HD64180
|
||||
#define _PT_Z80 0x02 // Z80
|
||||
#define _PT_8085 0x04 // Intel 8085
|
||||
#define _PT_Z180 0x08 // Z180
|
||||
#define _PT_Z380 0x10 // Z380
|
||||
#define _PT_GB 0x20 // GameBoy
|
||||
|
||||
#define PT_GB _PT_GB
|
||||
#define PT_Z380 _PT_Z380
|
||||
#define PT_Z180 ( PT_Z380 | _PT_Z180)
|
||||
#define PT_64180 ( PT_Z180 | _PT_64180)
|
||||
#define PT_Z80 ( PT_64180| _PT_Z80 | _PT_GB)
|
||||
#define PT_8085 ( PT_Z80 | _PT_8085 )
|
||||
|
||||
extern int pflag;
|
||||
|
||||
enum RegNo ENUM_SIZE(uint16)
|
||||
{
|
||||
R_b = 0,
|
||||
R_c = 1,
|
||||
R_d = 2,
|
||||
R_e = 3,
|
||||
R_h = 4,
|
||||
R_l = 5,
|
||||
R_a = 7,
|
||||
R_bc = 8,
|
||||
R_de = 9,
|
||||
R_hl = 10,
|
||||
R_af = 11,
|
||||
R_sp = 12,
|
||||
R_ix = 13,
|
||||
R_iy = 14,
|
||||
R_af2 = 15,
|
||||
R_r = 16,
|
||||
R_i = 17,
|
||||
R_f = 18,
|
||||
R_xl = 19,
|
||||
R_xh = 20,
|
||||
R_yl = 21,
|
||||
R_yh = 22,
|
||||
|
||||
R_w,
|
||||
R_lw,
|
||||
R_ixl,
|
||||
R_ixu,
|
||||
R_dsr,
|
||||
R_xsr,
|
||||
R_iyl,
|
||||
R_iyu,
|
||||
R_ysr,
|
||||
R_sr,
|
||||
R_ib,
|
||||
R_iw,
|
||||
R_xm,
|
||||
R_lck,
|
||||
R_bc2,
|
||||
R_de2,
|
||||
R_hl2,
|
||||
R_ix2,
|
||||
R_iy2,
|
||||
R_b2,
|
||||
R_c2,
|
||||
R_d2,
|
||||
R_e2,
|
||||
R_h2,
|
||||
R_l2,
|
||||
R_m2,
|
||||
R_a2,
|
||||
|
||||
R_vcs, // virtual code segment register
|
||||
R_vds // virtual data segment register
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
#define UAS_NOENS 0x0001 // I5: don't specify start addr in the .end directive
|
||||
#define UAS_NPAIR 0x0002 // I5: pairs are denoted by 1 char ('b')
|
||||
#define UAS_UNDOC 0x0004 // I5: does assembler support undoc-d instrs?
|
||||
#define UAS_MKIMM 0x0008 // I5: place # in front of imm operand
|
||||
#define UAS_MKOFF 0x0010 // I5: offset(ix) form
|
||||
#define UAS_CNDUP 0x0020 // I5: conditions UPPERCASE
|
||||
#define UAS_FUNNY 0x0040 // I5: special for A80
|
||||
#define UAS_CSEGS 0x0080 // I5: generate 'cseg' directives
|
||||
#define UAS_TOFF 0x0100 // I5: (ix+-10)
|
||||
#define UAS_ZMASM 0x0200 // ZMASM
|
||||
#define UAS_GBASM 0x0400 // RGBASM
|
||||
|
||||
|
||||
#define aux_off16 0x0001 // o_displ: off16
|
||||
|
||||
//------------------------------------------------------------------
|
||||
struct z80_iohandler_t : public iohandler_t
|
||||
{
|
||||
z80_iohandler_t(netnode &nn) : iohandler_t(nn) {}
|
||||
};
|
||||
|
||||
struct insndesc_t;
|
||||
struct z80_t : public procmod_t
|
||||
{
|
||||
netnode helper;
|
||||
z80_iohandler_t ioh = z80_iohandler_t(helper);
|
||||
|
||||
int pflag = 0;
|
||||
int code;
|
||||
|
||||
uchar saved_value = 0;
|
||||
bool flow = false;
|
||||
bool isx = false;
|
||||
|
||||
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
|
||||
|
||||
const char *find_ioport(uval_t port);
|
||||
const char *find_ioport_bit(int port, int bit);
|
||||
void choose_device(int respinfo);
|
||||
|
||||
void set_cpu(int np);
|
||||
void load_from_idb();
|
||||
|
||||
const char *set_idp_options(const char *keyword, int /*value_type*/, const void * /*value*/, bool /*idb_loaded*/);
|
||||
|
||||
// out.cpp
|
||||
inline bool isFunny(void) { return (ash.uflag & UAS_FUNNY) != 0; }
|
||||
void i5_header(outctx_t &ctx);
|
||||
void i5_footer(outctx_t &ctx);
|
||||
void i5_segstart(outctx_t &ctx, segment_t *);
|
||||
|
||||
// ana.cpp
|
||||
int i5_ana(insn_t *_insn);
|
||||
void load_z80_operand(insn_t &insn, op_t &x, uchar op);
|
||||
bool search_map(insn_t &insn, const insndesc_t *map, uchar _code);
|
||||
bool z380_insns(insn_t &insn, const insndesc_t *map, const insndesc_t *cb);
|
||||
bool z380_ED(insn_t &insn);
|
||||
void z80_ixcommands(insn_t &insn, bool _isx);
|
||||
void z80_misc(insn_t &insn);
|
||||
void ConvertToZ80(insn_t &insn);
|
||||
void op_r1(op_t &x) const;
|
||||
void op_r2(op_t &x) const;
|
||||
void op_ss(op_t &x) const;
|
||||
void op_dd(op_t &x) const;
|
||||
void op_xdispl(insn_t &insn, op_t &x) const;
|
||||
void op_ix(op_t &x) const;
|
||||
void op_ibyte(op_t &x,int low) const;
|
||||
int op_xbytereg(op_t &x,uint16 mode) const;
|
||||
int op_xr1(op_t &x) const;
|
||||
int op_xr2(op_t &x) const;
|
||||
inline bool isGB(void);
|
||||
inline bool isZ380(void);
|
||||
inline bool isZ180(void);
|
||||
inline bool isZ80(void);
|
||||
inline bool is64180(void);
|
||||
inline bool is8085(void);
|
||||
|
||||
// emu.cpp
|
||||
int i5_emu(const insn_t &insn);
|
||||
void load_operand(const insn_t &insn, const op_t &x);
|
||||
sval_t named_regval(const char *regname, getreg_t *getreg, const regval_t *rv);
|
||||
sval_t regval(const op_t &op, getreg_t *getreg, const regval_t *rv);
|
||||
bool check_cond(uint16_t cc, getreg_t *getreg, const regval_t *regvalues);
|
||||
ea_t next_exec_insn(
|
||||
ea_t ea,
|
||||
getreg_t *getreg,
|
||||
const regval_t *regvalues);
|
||||
ea_t calc_step_over(ea_t ip) const;
|
||||
bool get_operand_info(
|
||||
idd_opinfo_t *opinf,
|
||||
ea_t ea,
|
||||
int n,
|
||||
getreg_t *getreg,
|
||||
const regval_t *regvalues);
|
||||
bool get_reg_info(
|
||||
const char **main_regname,
|
||||
bitrange_t *bitrange,
|
||||
const char *regname);
|
||||
};
|
||||
|
||||
extern int data_id;
|
||||
#define PROCMOD_NAME z80
|
||||
#define PROCMOD_NODE_NAME "$ " QSTRINGIZE(PROCMOD_NAME)
|
||||
|
||||
|
||||
inline bool z80_t::isGB(void) { return (pflag & PT_GB) != 0; }
|
||||
inline bool z80_t::isZ380(void) { return (pflag & PT_Z380) != 0; }
|
||||
inline bool z80_t::isZ180(void) { return (pflag & PT_Z180) != 0; }
|
||||
inline bool z80_t::isZ80(void) { return (pflag & PT_Z80) != 0; }
|
||||
inline bool z80_t::is64180(void) { return (pflag & PT_64180) != 0; }
|
||||
inline bool z80_t::is8085(void) { return !isZ80(); }
|
||||
|
||||
#endif // I5HPP
|
||||
297
idasdk76/module/z80/ins.cpp
Normal file
297
idasdk76/module/z80/ins.cpp
Normal file
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Version 2.05
|
||||
* Copyright (c) 1990-93 by Ilfak Guilfanov. (2:5020/209@fidonet)
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ida.hpp>
|
||||
#include <idp.hpp>
|
||||
#include "ins.hpp"
|
||||
|
||||
const instruc_t Instructions[] =
|
||||
{
|
||||
|
||||
{ "", 0 }, // Unknown Operation
|
||||
|
||||
//
|
||||
// Intel 8080/8085 instructions
|
||||
//
|
||||
|
||||
{ "aci", CF_USE1 | CF_CHG1 | CF_USE2 }, // Add immediate to A with carry
|
||||
{ "adc", CF_USE1 | CF_CHG1 | CF_USE2 }, // Add reg to A with carry
|
||||
{ "add", CF_USE1 | CF_CHG1 | CF_USE2 }, // Add <reg> to A
|
||||
{ "adi", CF_USE1 | CF_CHG1 | CF_USE2 }, // Add immediate to A
|
||||
{ "ana", CF_USE1 | CF_CHG1 | CF_USE2 }, // And reg to A
|
||||
{ "ani", CF_USE1 | CF_CHG1 | CF_USE2 }, // And immediate to A
|
||||
{ "call", CF_USE1 | CF_CALL }, // Call subroutine at <addr>
|
||||
{ "cnz", CF_USE1 | CF_CALL }, // Call subroutine if non zero
|
||||
{ "cz", CF_USE1 | CF_CALL }, // Call subroutine if zero
|
||||
{ "cnc", CF_USE1 | CF_CALL }, // Call subroutine if carry clear
|
||||
{ "cc", CF_USE1 | CF_CALL }, // Call subroutine if carry set
|
||||
{ "cpo", CF_USE1 | CF_CALL }, // Call subroutine if odd parity
|
||||
{ "cpe", CF_USE1 | CF_CALL }, // Call subroutine if even parity
|
||||
{ "cp", CF_USE1 | CF_CALL }, // Call subroutine if positive
|
||||
{ "cm", CF_USE1 | CF_CALL }, // Call subroutine if negative
|
||||
{ "cmc", 0 }, // Complement carry
|
||||
{ "cmp", CF_USE1 | CF_USE2 }, // Compare register with A
|
||||
{ "cpi", CF_USE1 | CF_USE2 }, // Compare immediate data with A
|
||||
{ "cma", 0 }, // Complement A
|
||||
{ "daa", 0 }, // Decimal adjust A
|
||||
{ "dad", CF_USE1 | CF_CHG1 | CF_USE2 }, // Add register pair to HL
|
||||
{ "dcr", CF_USE1 | CF_CHG1 }, // Decrement register
|
||||
{ "dcx", CF_USE1 | CF_CHG1 }, // Decrement register pair
|
||||
{ "di", 0 }, // Disable interrupts
|
||||
{ "ei", 0 }, // Enable interrupts
|
||||
{ "hlt", 0 }, // Halt
|
||||
{ "in", CF_CHG1 | CF_USE2 }, // Input from port to A
|
||||
{ "inr", CF_USE1 | CF_CHG1 }, // Increment register
|
||||
{ "inx", CF_USE1 | CF_CHG1 }, // Increment register pair
|
||||
{ "jmp", CF_USE1 }, // Jump
|
||||
{ "jnz", CF_USE1 }, // Jump if not zero
|
||||
{ "jz", CF_USE1 }, // Jump if zero
|
||||
{ "jnc", CF_USE1 }, // Jump if carry clear
|
||||
{ "jc", CF_USE1 }, // Jump if carry set
|
||||
{ "jpo", CF_USE1 }, // Jump if parity odd
|
||||
{ "jpe", CF_USE1 }, // Jump if parity even
|
||||
{ "jp", CF_USE1 }, // Jump if plus
|
||||
{ "jm", CF_USE1 }, // Jump if minus
|
||||
{ "lda", CF_CHG1 | CF_USE2 }, // Load A direct from memory
|
||||
{ "ldax", CF_CHG1 | CF_USE2 }, // Load A indirect from memory using register pair
|
||||
{ "lhld", CF_CHG1 | CF_USE2 }, // Load HL direct from memory
|
||||
{ "lxi", CF_CHG1 | CF_USE2 }, // Load register pair with immediate data
|
||||
{ "mov", CF_CHG1 | CF_USE2 }, // Move register to register
|
||||
{ "mvi", CF_CHG1 | CF_USE2 }, // Move immediate data to register
|
||||
{ "nop", 0 }, // No Operation
|
||||
{ "ora", CF_USE1 | CF_CHG1 | CF_USE2 }, // Or register with A
|
||||
{ "ori", CF_USE1 | CF_CHG1 | CF_USE2 }, // Or immediate data to A
|
||||
{ "out", CF_USE1 | CF_USE2 }, // Output to port
|
||||
{ "pchl", CF_JUMP | CF_STOP }, // Jump to instruction at (HL)
|
||||
{ "pop", CF_CHG1 }, // Pop register pair from stack
|
||||
{ "push", CF_USE1 }, // Push register pair onto stack
|
||||
{ "ret", CF_STOP }, // Return from subroutine
|
||||
{ "rnz", 0 }, // Return if non zero
|
||||
{ "rz", 0 }, // Return if zero
|
||||
{ "rnc", 0 }, // Return if carry clear
|
||||
{ "rc", 0 }, // Return if carry set
|
||||
{ "rpo", 0 }, // Return if parity odd
|
||||
{ "rpe", 0 }, // Return if parity even
|
||||
{ "rp", 0 }, // Return if plus
|
||||
{ "rm", 0 }, // Return if minus
|
||||
{ "ral", 0 }, // Rotate A left with carry
|
||||
{ "rlc", 0 }, // Rotate A left with branch carry
|
||||
{ "rar", 0 }, // Rotate A right with carry
|
||||
{ "rrc", 0 }, // Rotate A right with branch carry
|
||||
{ "rst", CF_USE1 }, // Restart at vector <int>
|
||||
{ "sbb", CF_USE1 | CF_CHG1 | CF_USE2 }, // Subtract from A with borrow
|
||||
{ "sbi", CF_USE1 | CF_CHG1 | CF_USE2 }, // Subtract immediate from A with borrow
|
||||
{ "stc", 0 }, // Set carry
|
||||
{ "sphl", 0 }, // Exchange SP with HL
|
||||
{ "sta", CF_CHG1 | CF_USE2 }, // Store A direct memory
|
||||
{ "stax", CF_CHG1 | CF_USE2 }, // Store A indirect using register pair
|
||||
{ "shld", CF_CHG1 | CF_USE2 }, // Store HL
|
||||
{ "sui", CF_USE1 | CF_CHG1 | CF_USE2 }, // Subtract immediate from A
|
||||
{ "sub", CF_USE1 | CF_CHG1 | CF_USE2 }, // Subtract from A
|
||||
{ "xra", CF_USE1 | CF_CHG1 | CF_USE2 }, // XOR with A
|
||||
{ "xri", CF_USE1 | CF_CHG1 | CF_USE2 }, // XOR A with immediate data
|
||||
{ "xchg", 0 }, // Exchange DE with HL
|
||||
{ "xthl", 0 }, // Exchange HL with top of stack
|
||||
{ "rim", 0 }, // Read interrupt mask
|
||||
{ "sim", 0 }, // Store Interrupt mask
|
||||
|
||||
//
|
||||
// Z80 instructions
|
||||
//
|
||||
|
||||
{ "and", CF_USE1 | CF_USE2 | CF_CHG1 }, // And with accumulator
|
||||
{ "bit", CF_USE1 | CF_USE2 }, // Test <bit> in operand
|
||||
{ "call", CF_USE2 | CF_CALL }, // call (cond & uncond)
|
||||
{ "ccf", 0 }, // Complement carry flag
|
||||
{ "cp", CF_USE1 | CF_USE2 }, // Compare with accumulator
|
||||
{ "cpd", 0 }, // Compare accumulator with memory and\ndecrement address and byte counters
|
||||
{ "cpdr", 0 }, // Compare accumulator with memory and\ndecrement address and byte counter,\ncontinue until match is found or\nbyte counter is zero
|
||||
{ "cpi", 0 }, // Compare accumulator with memory and\nincrement address and byte counters
|
||||
{ "cpir", 0 }, // Compare accumulator with memory and\nincrement address and byte counter,\ncontinue until match is found or\nbyte counter is zero
|
||||
{ "cpl", 0 }, // Complement the accumulator
|
||||
{ "dec", CF_USE1 | CF_CHG1 }, // Decrement operand
|
||||
{ "djnz", CF_USE1 }, // Decrement reg B and jump relative if zero
|
||||
{ "ex", CF_USE1 | CF_CHG1 | CF_USE2 | CF_CHG2 }, // Exchange operands
|
||||
{ "exx", 0 }, // Exchange register pairs and alt reg pairs
|
||||
{ "halt", 0 }, // Program execution stops
|
||||
{ "im", CF_USE1 }, // Interrupt mode
|
||||
{ "inc", CF_USE1 | CF_CHG1 }, // Increment operand
|
||||
{ "ind", 0 }, // Input to memory and decrement pointer
|
||||
{ "indr", 0 }, // Input to memory and decrement pointer until\nbyte counter is zero
|
||||
{ "ini", 0 }, // Input to memory and increment pointer
|
||||
{ "inir", 0 }, // Input to memory and increment pointer until\nbyte counter is zero
|
||||
{ "jp", CF_USE2 }, // Jump (conditional & unconditional)
|
||||
{ "jr", CF_USE1 | CF_USE2 }, // Jump relative (conditional & unconditional)
|
||||
{ "ld", CF_CHG1 | CF_USE2 }, // Move operand2 to operand1
|
||||
{ "ldd", 0 }, // Transfer data between memory and decrement\ndestination and source addresses
|
||||
{ "lddr", 0 }, // Transfer data between memory until byte\ncounter is zero, decrement destintation\nand source addresses
|
||||
{ "ldi", 0 }, // Transfer data between memory and increment\ndestination and source addresses
|
||||
{ "ldir", 0 }, // Transfer data between memory until byte\ncounter is zero, increment destination\nand source addresses
|
||||
{ "neg", 0 }, // Negate contents of accumulator
|
||||
{ "or", CF_USE1 | CF_CHG1 | CF_USE2 }, // Or with accumulator
|
||||
{ "otdr", 0 }, // Output from memory, decrement address\ncontinue until reg B is zero
|
||||
{ "otir", 0 }, // Output from memory, increment address\ncontinue until reg B is zero
|
||||
{ "outd", 0 }, // Output from memory, decrement address
|
||||
{ "outi", 0 }, // Output from memory, increment address
|
||||
{ "res", CF_USE1 | CF_CHG2 | CF_USE2 }, // Reset bit
|
||||
{ "ret", 0 }, // Return (cond & uncond)
|
||||
{ "reti", CF_STOP }, // Return from interrupt
|
||||
{ "retn", CF_STOP }, // Return from non-maskable interrupt
|
||||
{ "rl", CF_USE1 | CF_CHG1 }, // Rotate left through carry
|
||||
{ "rla", 0 }, // Rotate left through carry accumulator
|
||||
{ "rlc", CF_USE1 | CF_CHG1 }, // Rotate left branch carry
|
||||
{ "rlca", 0 }, // Rotate left accumulator
|
||||
{ "rld", 0 }, // Rotate one BCD digit left between the\naccumulator and memory
|
||||
{ "rr", CF_USE1 | CF_CHG1 }, // Rotate right through carry
|
||||
{ "rra", 0 }, // Rotate right through carry accumulator
|
||||
{ "rrc", CF_USE1 | CF_CHG1 }, // Rotate right branch carry
|
||||
{ "rrca", 0 }, // Rotate right branch carry accumulator
|
||||
{ "rrd", 0 }, // Rotate one BCD digit right between the\naccumulator and memory
|
||||
{ "scf", 0 }, // Set carry flag
|
||||
{ "sbc", CF_USE1 | CF_CHG1 | CF_USE2 }, // Subtract from A with borrow
|
||||
{ "set", CF_USE1 | CF_CHG2 | CF_USE2 }, // Set bit
|
||||
{ "sla", CF_USE1 | CF_CHG1 }, // Shift left arithmetic
|
||||
{ "sra", CF_USE1 | CF_CHG1 }, // Shift right arithmetic
|
||||
{ "srl", CF_USE1 | CF_CHG1 }, // Shift right logical
|
||||
{ "xor", CF_USE1 | CF_CHG1 | CF_USE2 }, // Exclusive or with accumulator
|
||||
{ "inp", CF_USE1 }, // Input from port (c) into operand
|
||||
{ "outp", CF_USE1 }, // Output operand to port (c)
|
||||
{ "srr", CF_USE1 }, // Shift left filling with 1
|
||||
//
|
||||
// HD64180 extensions
|
||||
//
|
||||
{ "in0", CF_USE1 | CF_CHG1 | CF_USE2 }, // load register with input from port (n)
|
||||
{ "mlt", CF_USE1 }, // multiplication of each half\nof the specified register pair\nwith the 16-bit result going to\nthe specified register pair
|
||||
{ "otim", 0 }, // load output port (c) with\nlocation (hl),\nincrement hl and b\ndecrement c
|
||||
{ "otimr", 0 }, // load output port (c) with\nlocation (hl),\nincrement hl and c\ndecrement b\nrepeat until b = 0
|
||||
{ "otdm", 0 }, // load output port (c) with\nlocation (hl),\ndecrement hl and b\ndecrement c
|
||||
{ "otdmr", 0 }, // load output port (c) with\nlocation (hl),\ndecrement hl and c\ndecrement b\nrepeat until b = 0
|
||||
{ "out0", CF_USE1 }, // load output port (n) from register
|
||||
{ "slp", 0 }, // enter sleep mode
|
||||
{ "tst", CF_USE1 }, // non-destructive'and' with accumulator and specified operand
|
||||
{ "tstio", CF_USE1 }, // non-destructive 'and' of n and the contents of port (c)
|
||||
//
|
||||
// A80 special instructions
|
||||
//
|
||||
{ "lbcd", CF_CHG1 | CF_USE2 }, // Move operand to BC
|
||||
{ "lded", CF_CHG1 | CF_USE2 }, // Move operand to DE
|
||||
{ "lspd", CF_CHG1 | CF_USE2 }, // Move operand to SP
|
||||
{ "lixd", CF_CHG1 | CF_USE2 }, // Move operand to IX
|
||||
{ "liyd", CF_CHG1 | CF_USE2 }, // Move operand to IY
|
||||
{ "sbcd", CF_CHG1 | CF_USE2 }, // Move BC to memory
|
||||
{ "sded", CF_CHG1 | CF_USE2 }, // Move DE to memory
|
||||
{ "sspd", CF_CHG1 | CF_USE2 }, // Move SP to memory
|
||||
{ "sixd", CF_CHG1 | CF_USE2 }, // Move IX to memory
|
||||
{ "siyd", CF_CHG1 | CF_USE2 }, // Move IY to memory
|
||||
{ "xtix", CF_USE1 | CF_CHG1 | CF_USE2 | CF_CHG2 }, // Exchange SP and IX
|
||||
{ "xtiy", CF_USE1 | CF_CHG1 | CF_USE2 | CF_CHG2 }, // Exchange SP and IY
|
||||
{ "spix", CF_CHG1 | CF_USE2 }, // Move IX to SP
|
||||
{ "spiy", CF_CHG1 | CF_USE2 }, // Move IY to SP
|
||||
{ "pcix", CF_USE2 | CF_STOP }, // Jump indirect by IX
|
||||
{ "pciy", CF_USE2 | CF_STOP }, // Jump indirect by IY
|
||||
{ "mvra", CF_CHG1 | CF_USE2 }, // Move A to R
|
||||
{ "mvia", CF_CHG1 | CF_USE2 }, // Move A to I
|
||||
{ "mvar", CF_CHG1 | CF_USE2 }, // Move R to A
|
||||
{ "mvai", CF_CHG1 | CF_USE2 }, // Move I to A
|
||||
{ "dadix", CF_USE1 | CF_CHG1 | CF_USE2 }, // Add operand to IX
|
||||
{ "dadiy", CF_USE1 | CF_CHG1 | CF_USE2 }, // Add operand to IY
|
||||
{ "addc", CF_USE1 | CF_CHG1 | CF_USE2 }, // Add operand to HL with carry
|
||||
{ "addcix", CF_USE1 | CF_CHG1 | CF_USE2 }, // Add operand to IX with carry
|
||||
{ "addciy", CF_USE1 | CF_CHG1 | CF_USE2 }, // Add operand to IY with carry
|
||||
{ "subc", CF_USE1 | CF_CHG1 | CF_USE2 }, // Subtract from HL with borrow
|
||||
{ "subcix", CF_USE1 | CF_CHG1 | CF_USE2 }, // Subtract from IX with borrow
|
||||
{ "subciy", CF_USE1 | CF_CHG1 | CF_USE2 }, // Subtract from IY with borrow
|
||||
{ "jrc", CF_USE2 }, // Jump relative if carry
|
||||
{ "jrnc", CF_USE2 }, // Jump relative if not carry
|
||||
{ "jrz", CF_USE2 }, // Jump relative if zero
|
||||
{ "jrnz", CF_USE2 }, // Jump relative if not zero
|
||||
{ "cmpi", 0 }, // Compare accumulator with memory and\nincrement address and byte counters
|
||||
{ "cmpd", 0 }, // Compare accumulator with memory and\ndecrement address and byte counters
|
||||
{ "im0", CF_USE1 }, // Interrupt mode 0
|
||||
{ "im1", CF_USE1 }, // Interrupt mode 1
|
||||
{ "im2", CF_USE1 }, // Interrupt mode 2
|
||||
{ "otd", 0 }, // Output from memory, decrement address
|
||||
{ "oti", 0 }, // Output from memory, increment address
|
||||
|
||||
// Intel 8085 undocumented instructions
|
||||
// (info from http://oak.oakland.edu/pub/cpm/maclib/i8085.lib)
|
||||
|
||||
{ "dsub", 0 }, // (HL) <- (HL)-(BC), affects all flags
|
||||
{ "arhl", 0 }, // SHIFT HL RIGHT ONE BIT, (H7 IS DUPLICATED, L0 IS SHIFTED INTO CY)
|
||||
{ "rdel", 0 }, // ROTATE DE LEFT ONE BIT THRU CY, (E0 RECEIVES CY, CY RECEIVES D7)
|
||||
{ "ldhi", CF_USE1 }, // (DE) <- (HL)+arg
|
||||
{ "ldsi", CF_USE1 }, // (DE) <- (SP)+arg
|
||||
{ "shlx", 0 }, // ((DE)) <- (HL)
|
||||
{ "lhlx", 0 }, // (HL) <- ((DE))
|
||||
{ "rstv", 0 }, // RESTART 40H ON V (OVERFLOW)
|
||||
{ "jx5", CF_USE1 }, // JUMP IF X5 SET
|
||||
{ "jnx5", CF_USE1 }, // JUMP IF NOT X5 SET
|
||||
|
||||
// Z380 instructions
|
||||
|
||||
{ "cplw", CF_USE1 }, // Complement HL register
|
||||
{ "swap", CF_USE1 }, // Swap upper register word with lower register word
|
||||
{ "inw", CF_CHG1|CF_USE2 }, // Input word
|
||||
{ "outw", CF_CHG1|CF_USE2 }, // Output word
|
||||
{ "ldw", CF_CHG1|CF_USE2 }, // Load word
|
||||
{ "addw", CF_CHG1|CF_USE2 }, // Add word
|
||||
{ "subw", CF_CHG1|CF_USE2 }, // Subtract word
|
||||
{ "adcw", CF_CHG1|CF_USE2 }, // Add with carry word
|
||||
{ "sbcw", CF_CHG1|CF_USE2 }, // Subtract with borrow word
|
||||
{ "andw", CF_CHG1|CF_USE2 }, // AND logical word
|
||||
{ "xorw", CF_CHG1|CF_USE2 }, // XOR logical word
|
||||
{ "orw", CF_CHG1|CF_USE2 }, // OR logical word
|
||||
{ "cpw", CF_CHG1|CF_USE2 }, // Compare word
|
||||
{ "ddir", CF_USE1 }, // Decoder directive
|
||||
{ "calr", CF_USE1|CF_USE2 }, // Call relative
|
||||
{ "ldctl", CF_CHG1|CF_USE2 }, // Load control register
|
||||
{ "mtest", CF_USE1 }, // Mode test
|
||||
{ "exxx", CF_USE1 }, // Exchange Index Register with Alternate Bank
|
||||
{ "exxy", CF_USE1 }, // Exchange Index Register with Alternate Bank
|
||||
{ "exall", CF_USE1 }, // Exchange all registers with Alternate Bank
|
||||
{ "setc", CF_USE1 }, // Set control bit
|
||||
{ "resc", CF_USE1 }, // Reset control bit
|
||||
{ "rlcw", CF_USE1 }, // Rotate Left Circular Word
|
||||
{ "rrcw", CF_USE1 }, // Rotate Right Circular Word
|
||||
{ "rlw", CF_USE1 }, // Rotate Left Word
|
||||
{ "rrw", CF_USE1 }, // Rotate Right Word
|
||||
{ "slaw", CF_USE1 }, // Shift Left Arithmetic Word
|
||||
{ "sraw", CF_USE1 }, // Shift Right Arithmetic Word
|
||||
{ "srlw", CF_USE1 }, // Shift Right Logical Word
|
||||
{ "multw", CF_USE1 }, // Multiply Word
|
||||
{ "multuw", CF_USE1 }, // Multiply Word Unsigned
|
||||
{ "divuw", CF_USE1 }, // Divide unsigned
|
||||
{ "outaw", CF_CHG1|CF_USE1 }, // Output word direct to port address
|
||||
{ "inaw", CF_CHG1|CF_USE1 }, // Input word direct from port address
|
||||
{ "outa", CF_CHG1|CF_USE1 }, // Output byte direct to port address
|
||||
{ "ina", CF_CHG1|CF_USE1 }, // Input byte direct from port address
|
||||
{ "negw", CF_CHG1 }, // Negate word
|
||||
{ "exts", CF_CHG1 }, // Extend byte sign
|
||||
{ "extsw", CF_CHG1 }, // Extend word sign
|
||||
{ "btest", 0 }, // Bank test
|
||||
{ "ldiw", 0 }, // Load and increment (word)
|
||||
{ "ldirw", 0 }, // Load and increment, repeat (word)
|
||||
{ "lddw", 0 }, // Load and decrement (word)
|
||||
{ "lddrw", 0 }, // Load and decrement, repeat (word)
|
||||
{ "iniw", 0 }, // Input and increment (word)
|
||||
{ "inirw", 0 }, // Input and increment, repeat (word)
|
||||
{ "indw", 0 }, // Input and decrement (word)
|
||||
{ "indrw", 0 }, // Input and decrement, repeat (word)
|
||||
{ "outiw", 0 }, // Output and increment (word)
|
||||
{ "otirw", 0 }, // Output and increment, repeat (word)
|
||||
{ "outdw", 0 }, // Output and decrement (word)
|
||||
{ "otdrw", 0 }, // Output and decrement, repeat (word)
|
||||
|
||||
// Gameboy instructions
|
||||
|
||||
{ "ldh", CF_CHG1|CF_USE2 },
|
||||
{ "stop", CF_STOP },
|
||||
|
||||
};
|
||||
|
||||
CASSERT(sizeof(Instructions)/sizeof(Instructions[0]) == I5_last);
|
||||
303
idasdk76/module/z80/ins.hpp
Normal file
303
idasdk76/module/z80/ins.hpp
Normal file
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2021 Hex-Rays
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __INSTRS_HPP
|
||||
#define __INSTRS_HPP
|
||||
|
||||
extern const instruc_t Instructions[];
|
||||
|
||||
enum nameNum ENUM_SIZE(uint16)
|
||||
{
|
||||
I5_null = 0, // Unknown Operation
|
||||
|
||||
//
|
||||
// Intel 8080-8085 instructions
|
||||
//
|
||||
|
||||
I5_aci,
|
||||
I5_adc, Z80_adc = I5_adc,
|
||||
I5_add, Z80_add = I5_add,
|
||||
I5_adi,
|
||||
I5_ana,
|
||||
I5_ani,
|
||||
I5_call,
|
||||
I5_cnz,
|
||||
I5_cz,
|
||||
I5_cnc,
|
||||
I5_cc,
|
||||
I5_cpo,
|
||||
I5_cpe,
|
||||
I5_cp,
|
||||
I5_cm,
|
||||
I5_cmc,
|
||||
I5_cmp,
|
||||
I5_cpi,
|
||||
I5_cma,
|
||||
I5_daa,
|
||||
I5_dad,
|
||||
I5_dcr,
|
||||
I5_dcx,
|
||||
I5_di, Z80_di = I5_di,
|
||||
I5_ei, Z80_ei = I5_ei,
|
||||
I5_halt,
|
||||
I5_in, Z80_in = I5_in,
|
||||
I5_inr,
|
||||
I5_inx,
|
||||
I5_jmp,
|
||||
I5_jnz,
|
||||
I5_jz,
|
||||
I5_jnc,
|
||||
I5_jc,
|
||||
I5_jpo,
|
||||
I5_jpe,
|
||||
I5_jp,
|
||||
I5_jm,
|
||||
I5_lda,
|
||||
I5_ldax,
|
||||
I5_lhld,
|
||||
I5_lxi,
|
||||
I5_mov,
|
||||
I5_mvi,
|
||||
I5_nop,
|
||||
I5_ora,
|
||||
I5_ori,
|
||||
I5_out, Z80_out = I5_out,
|
||||
I5_pchl,
|
||||
I5_pop, Z80_pop = I5_pop,
|
||||
I5_push, Z80_push = I5_push,
|
||||
I5_ret,
|
||||
I5_rnz,
|
||||
I5_rz,
|
||||
I5_rnc,
|
||||
I5_rc,
|
||||
I5_rpo,
|
||||
I5_rpe,
|
||||
I5_rp,
|
||||
I5_rm,
|
||||
I5_ral,
|
||||
I5_rlc,
|
||||
I5_rar,
|
||||
I5_rrc,
|
||||
I5_rst,
|
||||
I5_sbb,
|
||||
I5_sbi,
|
||||
I5_stc,
|
||||
I5_sphl,
|
||||
I5_sta,
|
||||
I5_stax,
|
||||
I5_shld,
|
||||
I5_sui,
|
||||
I5_sub, Z80_sub = I5_sub,
|
||||
I5_xra,
|
||||
I5_xri,
|
||||
I5_xchg,
|
||||
I5_xthl,
|
||||
|
||||
I5_rim,
|
||||
I5_sim,
|
||||
|
||||
//
|
||||
// Z80 extensions
|
||||
//
|
||||
|
||||
Z80_and,
|
||||
Z80_bit,
|
||||
Z80_call,
|
||||
Z80_ccf,
|
||||
Z80_cp,
|
||||
Z80_cpd,
|
||||
Z80_cpdr,
|
||||
Z80_cpi,
|
||||
Z80_cpir,
|
||||
Z80_cpl,
|
||||
Z80_dec,
|
||||
Z80_djnz,
|
||||
Z80_ex,
|
||||
Z80_exx,
|
||||
Z80_halt,
|
||||
Z80_im,
|
||||
Z80_inc,
|
||||
Z80_ind,
|
||||
Z80_indr,
|
||||
Z80_ini,
|
||||
Z80_inir,
|
||||
Z80_jp,
|
||||
Z80_jr,
|
||||
Z80_ld,
|
||||
Z80_ldd,
|
||||
Z80_lddr,
|
||||
Z80_ldi,
|
||||
Z80_ldir,
|
||||
Z80_neg,
|
||||
Z80_or,
|
||||
Z80_otdr,
|
||||
Z80_otir,
|
||||
Z80_outd,
|
||||
Z80_outi,
|
||||
Z80_res,
|
||||
Z80_ret,
|
||||
Z80_reti,
|
||||
Z80_retn,
|
||||
Z80_rl,
|
||||
Z80_rla,
|
||||
Z80_rlc,
|
||||
Z80_rlca,
|
||||
Z80_rld,
|
||||
Z80_rr,
|
||||
Z80_rra,
|
||||
Z80_rrc,
|
||||
Z80_rrca,
|
||||
Z80_rrd,
|
||||
Z80_scf,
|
||||
Z80_sbc,
|
||||
Z80_set,
|
||||
Z80_sla,
|
||||
Z80_sra,
|
||||
Z80_srl,
|
||||
Z80_xor,
|
||||
Z80_inp, // undocumented
|
||||
Z80_outp, // undocumented
|
||||
Z80_srr, // undocumented
|
||||
|
||||
//
|
||||
// HD64180 extensions
|
||||
//
|
||||
|
||||
HD_in0, Z80_in0 = HD_in0,
|
||||
HD_mlt, Z80_mlt = HD_mlt,
|
||||
HD_otim, Z80_otim = HD_otim,
|
||||
HD_otimr, Z80_otimr = HD_otimr,
|
||||
HD_otdm, Z80_otdm = HD_otdm,
|
||||
HD_otdmr, Z80_otdmr = HD_otdmr,
|
||||
HD_out0, Z80_out0 = HD_out0,
|
||||
HD_slp, Z80_slp = HD_slp,
|
||||
HD_tst, Z80_tst = HD_tst,
|
||||
HD_tstio, Z80_tstio = HD_tstio,
|
||||
|
||||
//
|
||||
// A80 special instructions
|
||||
//
|
||||
|
||||
A80_lbcd,
|
||||
A80_lded,
|
||||
A80_lspd,
|
||||
A80_lixd,
|
||||
A80_liyd,
|
||||
A80_sbcd,
|
||||
A80_sded,
|
||||
A80_sspd,
|
||||
A80_sixd,
|
||||
A80_siyd,
|
||||
A80_xtix,
|
||||
A80_xtiy,
|
||||
A80_spix,
|
||||
A80_spiy,
|
||||
A80_pcix,
|
||||
A80_pciy,
|
||||
A80_mvra,
|
||||
A80_mvia,
|
||||
A80_mvar,
|
||||
A80_mvai,
|
||||
A80_addix,
|
||||
A80_addiy,
|
||||
A80_addc,
|
||||
A80_addcix,
|
||||
A80_addciy,
|
||||
A80_subc,
|
||||
A80_subcix,
|
||||
A80_subciy,
|
||||
A80_jrc,
|
||||
A80_jrnc,
|
||||
A80_jrz,
|
||||
A80_jrnz,
|
||||
A80_cmpi,
|
||||
A80_cmpd,
|
||||
A80_im0,
|
||||
A80_im1,
|
||||
A80_im2,
|
||||
A80_otd,
|
||||
A80_oti,
|
||||
|
||||
// Intel 8085 undocumented instructions
|
||||
// (info from http://oak.oakland.edu/pub/cpm/maclib/i8085.lib)
|
||||
|
||||
I5_dsub, // (HL) <- (HL)-(BC), affects all flags
|
||||
I5_arhl, // SHIFT HL RIGHT ONE BIT, (H7 IS DUPLICATED, L0 IS SHIFTED INTO CY)
|
||||
I5_rdel, // ROTATE DE LEFT ONE BIT THRU CY, (E0 RECEIVES CY, CY RECEIVES D7)
|
||||
I5_ldhi, // (DE) <- (HL)+arg
|
||||
I5_ldsi, // (DE) <- (SP)+arg
|
||||
I5_shlx, // ((DE)) <- (HL)
|
||||
I5_lhlx, // (HL) <- ((DE))
|
||||
I5_rstv, // RESTART 40H ON V (OVERFLOW)
|
||||
I5_jx5, // JUMP IF X5 SET
|
||||
I5_jnx5, // JUMP IF NOT X5 SET
|
||||
|
||||
// Z380 instructions
|
||||
|
||||
Z80_cplw, // Complement HL register
|
||||
Z80_swap, // Swap upper register word with lower register word
|
||||
Z80_inw, // Input word
|
||||
Z80_outw, // Output word
|
||||
Z80_ldw, // Load word
|
||||
Z80_addw, // Add word
|
||||
Z80_subw, // Subtract word
|
||||
Z80_adcw, // Add with carry word
|
||||
Z80_sbcw, // Subtract with borrow word
|
||||
Z80_andw, // AND logical word
|
||||
Z80_xorw, // XOR logical word
|
||||
Z80_orw, // OR logical word
|
||||
Z80_cpw, // Compare word
|
||||
Z80_ddir, // Decoder directive
|
||||
Z80_calr, // Call relative
|
||||
Z80_ldctl, // Load control register
|
||||
Z80_mtest, // Mode test
|
||||
Z80_exxx, // Exchange Index Register with Alternate Bank
|
||||
Z80_exxy, // Exchange Index Register with Alternate Bank
|
||||
Z80_exall, // Exchange all registers with Alternate Bank
|
||||
Z80_setc, // Set control bit
|
||||
Z80_resc, // Reset control bit
|
||||
Z80_rlcw, // Rotate Left Circular Word
|
||||
Z80_rrcw, // Rotate Right Circular Word
|
||||
Z80_rlw, // Rotate Left Word
|
||||
Z80_rrw, // Rotate Right Word
|
||||
Z80_slaw, // Shift Left Arithmetic Word
|
||||
Z80_sraw, // Shift Right Arithmetic Word
|
||||
Z80_srlw, // Shift Right Logical Word
|
||||
Z80_multw, // Multiply Word
|
||||
Z80_multuw, // Multiply Word Unsigned
|
||||
Z80_divuw, // Divide unsigned
|
||||
Z80_outaw, // Output word direct to port address
|
||||
Z80_inaw, // Input word direct from port address
|
||||
Z80_outa, // Output byte direct to port address
|
||||
Z80_ina, // Input byte direct from port address
|
||||
Z80_negw, // Negate word
|
||||
Z80_exts, // Extend byte sign
|
||||
Z80_extsw, // Extend word sign
|
||||
Z80_btest, // Bank test
|
||||
Z80_ldiw, // Load and increment (word)
|
||||
Z80_ldirw, // Load and increment, repeat (word)
|
||||
Z80_lddw, // Load and decrement (word)
|
||||
Z80_lddrw, // Load and decrement, repeat (word)
|
||||
Z80_iniw, // Input and increment (word)
|
||||
Z80_inirw, // Input and increment, repeat (word)
|
||||
Z80_indw, // Input and decrement (word)
|
||||
Z80_indrw, // Input and decrement, repeat (word)
|
||||
Z80_outiw, // Output and increment (word)
|
||||
Z80_otirw, // Output and increment, repeat (word)
|
||||
Z80_outdw, // Output and decrement (word)
|
||||
Z80_otdrw, // Output and decrement, repeat (word)
|
||||
|
||||
// Gameboy instructions
|
||||
|
||||
GB_ldh,
|
||||
GB_stop,
|
||||
|
||||
I5_last,
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
52
idasdk76/module/z80/makefile
Normal file
52
idasdk76/module/z80/makefile
Normal file
@@ -0,0 +1,52 @@
|
||||
PROC=z80
|
||||
CONFIGS=z180.cfg
|
||||
|
||||
|
||||
include ../module.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \
|
||||
$(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \
|
||||
$(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
|
||||
ana.cpp i5.hpp ins.hpp
|
||||
$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \
|
||||
$(I)idd.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
|
||||
emu.cpp i5.hpp ins.hpp
|
||||
$(F)ins$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \
|
||||
$(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \
|
||||
$(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp \
|
||||
$(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ins.cpp ins.hpp
|
||||
$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \
|
||||
$(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \
|
||||
$(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
|
||||
i5.hpp ins.hpp out.cpp
|
||||
$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \
|
||||
$(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \
|
||||
$(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
|
||||
i5.hpp ins.hpp reg.cpp
|
||||
321
idasdk76/module/z80/out.cpp
Normal file
321
idasdk76/module/z80/out.cpp
Normal file
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Version 2.06
|
||||
* Copyright (c) 1990-93 by Ilfak Guilfanov. (2:5020/209@fidonet)
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "i5.hpp"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
class out_z80_t : public outctx_t
|
||||
{
|
||||
out_z80_t(void) = delete; // not used
|
||||
z80_t &pm() { return *static_cast<z80_t *>(procmod); }
|
||||
|
||||
public:
|
||||
void OutReg(int rgnum);
|
||||
bool out_operand(const op_t &x);
|
||||
void out_insn(void);
|
||||
};
|
||||
CASSERT(sizeof(out_z80_t) == sizeof(outctx_t));
|
||||
|
||||
DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_z80_t)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static const char *const condNames[] =
|
||||
{
|
||||
"nz",
|
||||
"z",
|
||||
"nc",
|
||||
"c",
|
||||
"po",
|
||||
"pe",
|
||||
"p",
|
||||
"m"
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_z80_t::OutReg(int rgnum)
|
||||
{
|
||||
if ( (ash.uflag & UAS_NPAIR) != 0 )
|
||||
{
|
||||
switch ( rgnum )
|
||||
{
|
||||
case R_bc: out_register(ph.reg_names[R_b]); return;
|
||||
case R_de: out_register(ph.reg_names[R_d]); return;
|
||||
case R_hl: out_register(ph.reg_names[R_h]); return;
|
||||
}
|
||||
}
|
||||
if ( rgnum == R_af && pm().isZ80() && !pm().isFunny() )
|
||||
out_register("af");
|
||||
else
|
||||
out_register(ph.reg_names[rgnum]);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool out_z80_t::out_operand(const op_t &x)
|
||||
{
|
||||
if ( !x.shown() )
|
||||
return false;
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_cond:
|
||||
if ( x.Cond == oc_not )
|
||||
return false;
|
||||
{
|
||||
char buf[3];
|
||||
qstrncpy(buf, condNames[ x.Cond ], sizeof(buf));
|
||||
if ( ash.uflag & UAS_CNDUP )
|
||||
qstrupr(buf);
|
||||
out_keyword(buf);
|
||||
}
|
||||
break;
|
||||
|
||||
case o_reg:
|
||||
OutReg(x.reg);
|
||||
break;
|
||||
|
||||
case o_displ: // Z80 only!!! + GB, one instruction
|
||||
if ( ash.uflag & UAS_MKOFF )
|
||||
out_value(x, OOF_ADDR|OOFW_16);
|
||||
if ( !pm().isGB() )
|
||||
out_symbol('(');
|
||||
OutReg(x.phrase);
|
||||
if ( !(ash.uflag & UAS_MKOFF) )
|
||||
{
|
||||
qstring buf;
|
||||
if ( is_off(F, x.n)
|
||||
&& get_offset_expression(&buf, insn.ea,x.n,insn.ea+x.offb,x.addr) )
|
||||
{
|
||||
out_symbol('+');
|
||||
out_line(buf.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
int offbit = (insn.auxpref & aux_off16) ? OOFW_16 : OOFW_8;
|
||||
int outf = OOF_ADDR|offbit|OOFS_NEEDSIGN;
|
||||
if ( ash.uflag & UAS_TOFF )
|
||||
outf |= OOF_SIGNED;
|
||||
out_value(x, outf);
|
||||
}
|
||||
}
|
||||
if ( !pm().isGB() )
|
||||
out_symbol(')');
|
||||
break;
|
||||
|
||||
case o_phrase:
|
||||
if ( pm().isZ80() && !pm().isFunny() )
|
||||
{
|
||||
out_symbol((ash.uflag & UAS_GBASM) ? '[' : '(');
|
||||
OutReg(x.phrase);
|
||||
out_symbol((ash.uflag & UAS_GBASM) ? ']' : ')');
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( x.phrase == R_hl )
|
||||
out_register("m");
|
||||
else
|
||||
OutReg(x.phrase);
|
||||
}
|
||||
break;
|
||||
|
||||
case o_void:
|
||||
return 0;
|
||||
|
||||
case o_imm:
|
||||
{
|
||||
const char *name = NULL;
|
||||
bool needbrace = false;
|
||||
if ( pm().isZ80() )
|
||||
{
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case I5_rst:
|
||||
if ( pm().isFunny() )
|
||||
{
|
||||
int radix = get_radix(F, x.n);
|
||||
out_long(x.value/8, radix);
|
||||
return 1;
|
||||
}
|
||||
case Z80_im:
|
||||
case Z80_bit:
|
||||
case Z80_res:
|
||||
case Z80_set:
|
||||
// name = pm().find_ioport_bit(x.value);
|
||||
break;
|
||||
case HD_in0:
|
||||
case HD_out0:
|
||||
name = pm().find_ioport(x.value);
|
||||
// fallthrough
|
||||
case I5_in:
|
||||
case I5_out:
|
||||
case Z80_outaw:
|
||||
case Z80_inaw:
|
||||
if ( !pm().isFunny() )
|
||||
{
|
||||
out_symbol('(');
|
||||
needbrace = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if ( ash.uflag & UAS_MKIMM )
|
||||
out_symbol('#');
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( name != NULL )
|
||||
out_line(name, COLOR_IMPNAME);
|
||||
else
|
||||
out_value(x, 0);
|
||||
if ( needbrace )
|
||||
out_symbol(')');
|
||||
}
|
||||
break;
|
||||
|
||||
case o_mem:
|
||||
if ( pm().isZ80() && !pm().isFunny() )
|
||||
out_symbol((ash.uflag & UAS_GBASM) ? '[' : '(');
|
||||
// no break
|
||||
case o_near:
|
||||
{
|
||||
ea_t v = map_ea(insn, x, x.type == o_near);
|
||||
if ( v == insn.ea && ash.a_curip != NULL )
|
||||
{
|
||||
out_line(ash.a_curip);
|
||||
}
|
||||
else if ( !out_name_expr(x, v, x.addr) )
|
||||
{
|
||||
out_tagon(COLOR_ERROR);
|
||||
out_btoa(x.addr,16);
|
||||
out_tagoff(COLOR_ERROR);
|
||||
remember_problem(PR_NONAME,insn.ea);
|
||||
}
|
||||
if ( x.type == o_mem && pm().isZ80() && !pm().isFunny() )
|
||||
out_symbol((ash.uflag & UAS_GBASM) ? ']' : ')');
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
warning("bad optype %x", x.type);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool isIxyByte(const op_t &x)
|
||||
{
|
||||
return x.type == o_reg
|
||||
&& (x.reg == R_xl
|
||||
|| x.reg == R_xh
|
||||
|| x.reg == R_yl
|
||||
|| x.reg == R_yh);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline bool isIxyOperand(const op_t &x)
|
||||
{
|
||||
return isIxyByte(x) || x.type == o_displ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_z80_t::out_insn(void)
|
||||
{
|
||||
out_mnemonic();
|
||||
|
||||
bool comma = out_one_operand(0);
|
||||
|
||||
if ( comma && insn.Op2.shown() && insn.Op2.type != o_void )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_symbol(' ');
|
||||
}
|
||||
|
||||
out_one_operand(1);
|
||||
|
||||
out_immchar_cmts();
|
||||
flush_outbuf();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void z80_t::i5_header(outctx_t &ctx)
|
||||
{
|
||||
ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX, ioh.device.c_str(), ioh.deviceparams.c_str());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//lint -esym(1764, ctx) could be made const
|
||||
//lint -esym(818, segm) could be made const
|
||||
void z80_t::i5_segstart(outctx_t &ctx, segment_t *segm)
|
||||
{
|
||||
qstring sname;
|
||||
get_segm_name(&sname, segm);
|
||||
|
||||
if ( ash.uflag & UAS_GBASM )
|
||||
{
|
||||
validate_name(&sname, VNT_IDENT);
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR("SECTION \"%s\", %s",SCOLOR_ASMDIR),
|
||||
sname.c_str(),
|
||||
segtype(ctx.insn_ea) == SEG_CODE ? "CODE" : "DATA");
|
||||
}
|
||||
else if ( ash.uflag & UAS_ZMASM )
|
||||
{
|
||||
const char *dir = "segment";
|
||||
if ( sname == ".text"
|
||||
|| sname == ".data"
|
||||
|| sname == ".bss" )
|
||||
{
|
||||
sname.clear();
|
||||
dir = sname.c_str();
|
||||
}
|
||||
else
|
||||
{
|
||||
validate_name(&sname, VNT_IDENT);
|
||||
}
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s",SCOLOR_ASMDIR), dir, sname.c_str());
|
||||
}
|
||||
else if ( ash.uflag & UAS_CSEGS )
|
||||
{
|
||||
validate_name(&sname, VNT_IDENT);
|
||||
ctx.gen_cmt_line("segment '%s'", sname.c_str());
|
||||
ctx.gen_printf(DEFAULT_INDENT,COLSTR("%cseg",SCOLOR_ASMDIR),segm->align == saAbs ? 'a' : 'c');
|
||||
}
|
||||
if ( (inf_get_outflags() & OFLG_GEN_ORG) != 0 )
|
||||
{
|
||||
ea_t org = ctx.insn_ea - get_segm_base(segm);
|
||||
if ( org != 0 )
|
||||
{
|
||||
char buf[MAX_NUMBUF];
|
||||
btoa(buf, sizeof(buf), org);
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void z80_t::i5_footer(outctx_t & ctx)
|
||||
{
|
||||
if ( ash.end != NULL )
|
||||
{
|
||||
ctx.gen_empty_line();
|
||||
ctx.out_line(ash.end, COLOR_ASMDIR);
|
||||
qstring name;
|
||||
if ( get_colored_name(&name, inf_get_start_ea()) > 0 )
|
||||
{
|
||||
if ( ash.uflag & UAS_NOENS )
|
||||
{
|
||||
ctx.out_char(' ');
|
||||
ctx.out_line(ash.cmnt);
|
||||
}
|
||||
ctx.out_char(' ');
|
||||
ctx.out_line(name.begin());
|
||||
}
|
||||
ctx.flush_outbuf(DEFAULT_INDENT);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.gen_cmt_line("end of file");
|
||||
}
|
||||
}
|
||||
1084
idasdk76/module/z80/reg.cpp
Normal file
1084
idasdk76/module/z80/reg.cpp
Normal file
File diff suppressed because it is too large
Load Diff
239
idasdk76/module/z80/z180.cfg
Normal file
239
idasdk76/module/z80/z180.cfg
Normal file
@@ -0,0 +1,239 @@
|
||||
.Z80180
|
||||
; Enhanced Z80 Megacell
|
||||
; http://www.zilog.com/products/partdetails.asp?id=Z80180
|
||||
|
||||
|
||||
; INPUT/ OUTPUT PORTS
|
||||
|
||||
CNTLA0 0x0000 ASCI Channel Control Register A 0
|
||||
CNTLA0.MPE 7 Multi-Processor Mode Enable
|
||||
CNTLA0.RE 6 Receiver Enable
|
||||
CNTLA0.TE 5 Transmitter Enable
|
||||
CNTLA0._RTS0 4 Request to Send Channel 0
|
||||
CNTLA0.MPBR_EFR 3 Multiprocessor Bit Receive/Error Flag Reset
|
||||
CNTLA0.MOD2 2 ASCI Data Format Mode 2
|
||||
CNTLA0.MOD1 1 ASCI Data Format Mode 1
|
||||
CNTLA0.MOD0 0 ASCI Data Format Mode 0
|
||||
|
||||
CNTLA1 0x0001 ASCI Channel Control Register A 0
|
||||
CNTLA1.MPE 7 Multi-Processor Mode Enable
|
||||
CNTLA1.RE 6 Receiver Enable
|
||||
CNTLA1.TE 5 Transmitter Enable
|
||||
CNTLA1._RTS0 4 Request to Send Channel 0
|
||||
CNTLA1.MPBR_EFR 3 Multiprocessor Bit Receive/Error Flag Reset
|
||||
CNTLA1.MOD2 2 ASCI Data Format Mode 2
|
||||
CNTLA1.MOD1 1 ASCI Data Format Mode 1
|
||||
CNTLA1.MOD0 0 ASCI Data Format Mode 0
|
||||
|
||||
CNTLB0 0x0002 ASCI Channel Control Register B 0
|
||||
CNTLB0.MPBT 7 Multiprocessor Bit Transmit
|
||||
CNTLB0.MP 6 Multiprocessor Mode
|
||||
CNTLB0.__CTS_PS 5 Clear to Send/Prescale
|
||||
CNTLB0.PEO 4 Parity Even Odd
|
||||
CNTLB0.DR 3 Divide Ratio
|
||||
CNTLB0.SS2 2 Source/Speed Select 2
|
||||
CNTLB0.SS1 1 Source/Speed Select 1
|
||||
CNTLB0.SS0 0 Source/Speed Select 0
|
||||
|
||||
CNTLB1 0x0003 ASCI Channel Control Register B 1
|
||||
CNTLB1.MPBT 7 Multiprocessor Bit Transmit
|
||||
CNTLB1.MP 6 Multiprocessor Mode
|
||||
CNTLB1.__CTS_PS 5 Clear to Send/Prescale
|
||||
CNTLB1.PEO 4 Parity Even Odd
|
||||
CNTLB1.DR 3 Divide Ratio
|
||||
CNTLB1.SS2 2 Source/Speed Select 2
|
||||
CNTLB1.SS1 1 Source/Speed Select 1
|
||||
CNTLB1.SS0 0 Source/Speed Select 0
|
||||
|
||||
STAT0 0x0004 ASCI Status Register 0
|
||||
STAT0.RDRF 7 Receive Data Register Full
|
||||
STAT0.OVRN 6 Overrun Error
|
||||
STAT0.PE 5 Parity Error
|
||||
STAT0.FE 4 Framing Error
|
||||
STAT0.REI 3 Receive Interrupt Enable
|
||||
STAT0._DCD0 2 Data Carrier Detect
|
||||
STAT0.TDRE 1 Transmit Data Register Empty
|
||||
STAT0.TIE 0 Transmit Interrupt Enable
|
||||
|
||||
STAT1 0x0005 ASCI Status Register 1
|
||||
STAT1.RDRF 7 Receive Data Register Full
|
||||
STAT1.OVRN 6 Overrun Error
|
||||
STAT1.PE 5 Parity Error
|
||||
STAT1.FE 4 Framing Error
|
||||
STAT1.REI 3 Receive Interrupt Enable
|
||||
STAT1.TDRE 1 Transmit Data Register Empty
|
||||
STAT1.TIE 0 Transmit Interrupt Enable
|
||||
|
||||
TDR0 0x0006
|
||||
TDR1 0x0007
|
||||
RDR0 0x0008
|
||||
RDR1 0x0009
|
||||
|
||||
CNTR 0x000A CSIO Control/Status Register
|
||||
CNTR.EF 7 End Flag
|
||||
CNTR.EIE 6 End Interrupt Enable
|
||||
CNTR.RE 5 Receive Enable
|
||||
CNTR.TE 4 Transmit Enable
|
||||
CNTR.SS2 2 Speed Select 2
|
||||
CNTR.SS1 1 Speed Select 1
|
||||
CNTR.SS0 0 Speed Select 0
|
||||
|
||||
TRDR 0x000B CSIO Transmit/Receive Data Register
|
||||
TMDR0L 0x000C Timer Data Register Channel 0L
|
||||
TMDR0H 0x000D Timer Data Register Channel 0H
|
||||
RLDR0L 0x000E Timer Reload Register 0L
|
||||
RLDR0H 0x000F Timer Reload Register 0H
|
||||
|
||||
TCR 0x0010 Timer Control Register
|
||||
TCR.TIF1 7 Timer Interrupt Flag 1
|
||||
TCR.TIF0 6 Timer Interrupt Flag 0
|
||||
TCR.TIE1 5 Timer Interrupt Enable 1
|
||||
TCR.TIE0 4 Timer Interrupt Enable 0
|
||||
TCR.TOC1 3 Timer Output Control
|
||||
TCR.TOC0 2 Timer Output Control
|
||||
TCR.TDE1 1
|
||||
TCR.TDE0 0
|
||||
|
||||
TMDR1L 0x0014 Timer Data Register Channel 1L
|
||||
TMDR1H 0x0015 Timer Data Register Channel 1H
|
||||
RLDR1L 0x0016 Timer Reload Register 1L
|
||||
RLDR1H 0x0017 Timer Reload Register 1H
|
||||
FRC 0x0018 Free Running Counter
|
||||
SAR0L 0x0020 DMA Source Address Register Channel 0L
|
||||
SAR0H 0x0021 DMA Source Address Register Channel 0H
|
||||
SAR0B 0x0022 DMA Source Address Register Channel 0B
|
||||
DAR0L 0x0023 DMA Destination Address Register Channel 0L
|
||||
DAR0H 0x0024 DMA Destination Address Register Channel 0H
|
||||
DAR0B 0x0025 DMA Destination Address Register Channel 0B
|
||||
BCR0L 0x0026 DMA Byte Count Register Channel 0L
|
||||
BCR0H 0x0027 DMA Byte Count Register Channel 0H
|
||||
MAR1L 0x0028 DMA Memory Address Register, Channel 1L
|
||||
MAR1H 0x0029 DMA Memory Address Register, Channel 1H
|
||||
MAR1B 0x002A DMA Memory Address Register, Channel 1B
|
||||
IAR1L 0x002B DMA I/O Address Register Channel 1L
|
||||
IAR1H 0x002C DMA I/O Address Register Channel 1H
|
||||
BCR1L 0x002E DMA Byte Count Register Channel 1L
|
||||
BCR1H 0x002F DMA Byte Count Register Channel 1H
|
||||
|
||||
DSTAT 0x0030 DMA Status Register
|
||||
DSTAT.DE1 7 DE1: DMA Enable Channel 1
|
||||
DSTAT.DE0 6 DE0: DMA Enable Channel 0
|
||||
DSTAT.DWE1 5 DE1 Bit WRITE Enable
|
||||
DSTAT.DWE0 4 DE0 Bit WRITE Enable
|
||||
DSTAT.DIE1 3 DMA Interrupt Enable Channel
|
||||
DSTAT.DIE0 2 DMA Interrupt Enable Channel
|
||||
DSTAT.DME 0 DMA Main Enable
|
||||
|
||||
DMODE 0x0031 DMA Mode Register
|
||||
DMODE.DM1 5 Destination Mode Channel 0
|
||||
DMODE.DM0 4 Destination Mode Channel 0
|
||||
DMODE.SM1 3 Source Mode Channel 0
|
||||
DMODE.SM0 2 Source Mode Channel 0
|
||||
DMODE.MMOD 1 Memory Mode Channel 0
|
||||
|
||||
DCNTL 0x0032 DMA/WAIT Control Register
|
||||
DCNTL.MWI1 7 Memory Wait Insertion
|
||||
DCNTL.MWI0 6 Memory Wait Insertion
|
||||
DCNTL.IWI1 5 I/O Wait Insertion
|
||||
DCNTL.IWI0 4 I/O Wait Insertion
|
||||
DCNTL.DMS1 3 DMA Request Sense
|
||||
DCNTL.DMS0 2 DMA Request Sense
|
||||
DCNTL.DIM1 1 DMA Channel 1 I/O and Memory Mode
|
||||
DCNTL.DIM0 0 DMA Channel 1 I/O and Memory Mode
|
||||
|
||||
IL 0x0033 Interrupt Vector Low Register
|
||||
IL.IL7 7
|
||||
IL.IL6 6
|
||||
IL.IL5 5
|
||||
|
||||
ITC 0x0034 Int/TRAP Control Register
|
||||
ITC.TRAP 7
|
||||
ITC.UFO 6 Undefined Fetch Object
|
||||
ITC.ITE2 2 Interrupt Enable 2
|
||||
ITC.ITE1 1 Interrupt Enable 1
|
||||
ITC.ITE0 0 Interrupt Enable 0
|
||||
|
||||
RCR 0x0036 Refresh Control Register
|
||||
RCR.REFE 7 Refresh Enable
|
||||
RCR.REFW 6 Refresh Wait
|
||||
RCR.CYC1 1 Cycle Interval
|
||||
RCR.CYC0 0 Cycle Interval
|
||||
|
||||
CBR 0x0038 MMU Common Base Register (CBR)
|
||||
CBR.CB7 7
|
||||
CBR.CB6 6
|
||||
CBR.CB5 5
|
||||
CBR.CB4 4
|
||||
CBR.CB3 3
|
||||
CBR.CB2 2
|
||||
CBR.CB1 1
|
||||
CBR.CB0 0
|
||||
|
||||
BBR 0x0039 MMU Bank Base Register (BBR)
|
||||
BBR.BB7 7
|
||||
BBR.BB6 6
|
||||
BBR.BB5 5
|
||||
BBR.BB4 4
|
||||
BBR.BB3 3
|
||||
BBR.BB2 2
|
||||
BBR.BB1 1
|
||||
BBR.BB0 0
|
||||
|
||||
CBAR 0x003A MMU Common/Bank Area Register (CBAR)
|
||||
CBAR.CA3 7
|
||||
CBAR.CA2 6
|
||||
CBAR.CA1 5
|
||||
CBAR.CA0 4
|
||||
CBAR.BA3 3
|
||||
CBAR.BA2 2
|
||||
CBAR.BA1 1
|
||||
CBAR.BA0 0
|
||||
|
||||
OMCR 0x003E Operation Mode Control Register
|
||||
OMCR.MIE 7
|
||||
OMCR._MITE 6
|
||||
OMCR._IOC 5
|
||||
|
||||
ICR 0x003F I/O Control Register (ICR)
|
||||
ICR.IOA7 7
|
||||
ICR.IOA6 6
|
||||
ICR.IOSTP 5
|
||||
|
||||
|
||||
|
||||
.Z80181
|
||||
; Smart Access Controller
|
||||
|
||||
.Z80182
|
||||
; ZiLOG Intelligent Peripheral (ZIPT)
|
||||
|
||||
.Z80189
|
||||
|
||||
.Z8S180
|
||||
; + Parallel I/O
|
||||
|
||||
.Z80195
|
||||
; Smart Peripheral Controller (ROMless)
|
||||
|
||||
.Z80L183
|
||||
; Mixed-Signal Z183 Internet Processor
|
||||
|
||||
.Z80S183
|
||||
; Mixed-Signal Z183 Internet Processor
|
||||
|
||||
.Z8L180
|
||||
; Enhanced Z80 Megacell
|
||||
|
||||
.Z8L180
|
||||
; Low-Voltage Version (3.3 V)
|
||||
|
||||
.Z8L182
|
||||
; ZiLOG Intelligent Peripheral (ZIPT) - Low Voltage Version
|
||||
|
||||
.Z8S180
|
||||
; Enhanced Z80 Megacell
|
||||
|
||||
.Z8L180
|
||||
; Low-Voltage Version (3.3 V)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user