update to ida 7.6, add builds

This commit is contained in:
2021-10-31 21:20:46 +02:00
parent e0e0f2be99
commit b1809fe2d9
1408 changed files with 279193 additions and 302468 deletions

354
idasdk76/module/z8/ana.cpp Normal file
View File

@@ -0,0 +1,354 @@
/*
* Interactive disassembler (IDA).
* Zilog Z8 module
*
*/
#include "z8.hpp"
//----------------------------------------------------------------------
static int adjust_reg_alias(int reg_no, uint16 rp, bool mem)
{
// special case for Tycoint
// we use the third nibble to map the registers to alternative names in 1000:2000
// aliases for regs in the same WRG are placed next to each other in 256-byte blocks
// e.g.
// 1400-140F first alias group for regs 40-4F
// 1410-141F second alias group for regs 40-4F
// 1420-142F third alias group for regs 40-4F
// ... etc
int subbank_no = ((rp & 0xF00) >> 8) - 1;
// assert: subbank_no in [-1, 0xE]
if ( subbank_no >= 0 )
{
int wrg_no;
if ( mem )
{
// WRG is the high nibble of the register number
wrg_no = (reg_no & 0xF0) >> 4;
if ( wrg_no < 0xF )
reg_no &= 0xF;
}
else
{
// WRG is the high nibble of the RP
wrg_no = (rp & 0xF0) >> 4;
}
if ( wrg_no < 0xF ) // don't alias system registers (F0-FF)
reg_no += 0x1000 + wrg_no * 256 + subbank_no * 16;
}
return reg_no;
}
//----------------------------------------------------------------------
static void work_reg(const insn_t &insn, op_t &op, int reg_no, int dbl_reg = 0, int indir = 0 )
{
if ( dbl_reg )
op.dtype = dt_word;
// do we have RP set?
uint16 rp = get_rp(insn.ea);
if ( rp == 0 )
{
// nope; use default working group (0)
op.reg = (dbl_reg ? rRR0 : rR0) + reg_no;
op.type = indir ? o_ind_reg : o_reg;
}
else
{
// use memory operand
if ( (rp & 0xF) == 0 && (rp & 0xF00) != 0 )
{
reg_no = adjust_reg_alias(reg_no, rp, false);
}
else
{
// high nibble of rp is the working group (bank), low nibble is the extended register file
reg_no += rp & 0xF0;
reg_no += (rp & 0xF) << 8;
}
op.addr = reg_no;
op.type = indir ? o_ind_mem : o_mem;
}
}
//----------------------------------------------------------------------
static void dir_reg(insn_t &insn, op_t &op, int dbl_reg = 0, int indir = 0)
{
uint tmp = insn.get_next_byte();
if ( (tmp & 0xF0 ) == 0xE0 ) // Ex - special reg bank
{
work_reg(insn, op, tmp & 0xF, dbl_reg, indir);
}
else
{
// use memory operand
uint16 rp = get_rp(insn.ea);
if ( (rp & 0xF) == 0 && (rp & 0xF00) != 0 )
tmp = adjust_reg_alias(tmp, rp, true);
op.addr = tmp;
op.type = indir ? o_ind_mem : o_mem;
if ( dbl_reg )
op.dtype = dt_word;
}
}
//----------------------------------------------------------------------
int z8_t::z8_ana(insn_t *_insn)
{
insn_t &insn = *_insn;
insn.Op1.dtype = dt_byte;
insn.Op2.dtype = dt_byte;
uint16 code = insn.get_next_byte();
uint16 nibble0 = (code & 0xF);
uint16 nibble1 = (code >> 4);
char offc;
uint16 tmp;
if ( nibble0 == 0xF ) // xF
{
static const char cmdxF[] =
{
Z8_null, Z8_null, Z8_null, Z8_null,
Z8_null, Z8_null, Z8_stop, Z8_halt,
Z8_di, Z8_ei, Z8_ret, Z8_iret,
Z8_rcf, Z8_scf, Z8_ccf, Z8_nop
};
insn.itype = cmdxF[nibble1];
}
else if ( nibble0 >= 8 ) // x8..xE
{
static const char cmdx8E[] =
{
Z8_ld, Z8_ld, Z8_djnz, Z8_jrcond, Z8_ld, Z8_jpcond, Z8_inc
};
insn.itype = cmdx8E[nibble0-8];
if ( nibble0 == 8 || nibble0 == 0xA || nibble0 == 0xC || nibble0 == 0xE )
{
work_reg(insn, insn.Op1, nibble1);
}
if ( nibble0 == 0xB || nibble0 == 0xD )
{
insn.Op1.type = o_phrase;
insn.Op1.phrase = nibble1;
}
switch ( nibble0 )
{
case 0x8: // ld r1,R2
dir_reg(insn, insn.Op2);
break;
case 0x9: // ld r2,R1
dir_reg(insn, insn.Op1);
work_reg(insn, insn.Op2, nibble1);
break;
case 0xA: // djnz r1,RA
case 0xB: // jr cc,RA
offc = insn.get_next_byte();
insn.Op2.addr = ushort(insn.ip + insn.size + offc); // signed addition
insn.Op2.dtype = dt_word;
insn.Op2.type = o_near;
break;
case 0xC: // ld r1,#im
insn.Op2.value = insn.get_next_byte();
insn.Op2.type = o_imm;
break;
case 0xD: // jp cc,DA
insn.Op2.addr = insn.get_next_word();
insn.Op2.dtype = dt_word;
insn.Op2.type = o_near;
}
if ( (nibble0 == 0xB || nibble0 == 0xD)
&& (nibble1 == 0 || nibble1 == 8) )
switch ( nibble1 )
{
case 0: // never true - seems as 2-byte NOP
insn.Op1.type = o_void;
insn.itype = Z8_nop;
insn.Op2.type = o_void;
break;
case 8:
insn.Op1 = insn.Op2;
insn.itype--; // Z8_jpcond -> Z8_jp, Z8_jrcond -> Z8_jr
insn.Op2.type = o_void;
}
}
else if ( nibble0 >= 2 ) // x2..x7
{
static const char cmdx2[] =
{
Z8_add, Z8_adc, Z8_sub, Z8_sbc,
Z8_or, Z8_and, Z8_tcm, Z8_tm,
Z8_null, Z8_null, Z8_cp, Z8_xor,
Z8_null, Z8_null, Z8_ld, Z8_null
};
switch ( code )
{
case 0xD6:
case 0xD4:
insn.itype = Z8_call;
insn.Op1.dtype = dt_word;
if ( code == 0xD6 )
{
insn.Op1.addr = insn.get_next_word();
insn.Op1.type = o_near;
}
else // D4 - call @RR
{
dir_reg(insn, insn.Op1, 1, 1);
}
break;
case 0xC7:
tmp = insn.get_next_byte();
work_reg(insn, insn.Op1, tmp >> 4);
insn.Op2.reg = tmp & 0xF;
insn.Op2.type = o_displ;
insn.Op2.addr = insn.get_next_byte();
insn.itype = Z8_ld;
break;
case 0xD7:
tmp = insn.get_next_byte();
work_reg(insn, insn.Op2, tmp >> 4);
insn.Op1.reg = tmp & 0xF;
insn.Op1.type = o_displ;
insn.Op1.addr = insn.get_next_byte();
insn.itype = Z8_ld;
break;
case 0x82: case 0x83: case 0x92: case 0x93:
tmp = insn.get_next_byte();
insn.itype = (nibble0 == 2) ? Z8_lde : Z8_ldei;
if ( nibble1 == 8 )
{
// r dst, lrr src
work_reg(insn, insn.Op1, tmp >> 4, 0, nibble0 != 2);
work_reg(insn, insn.Op2, tmp & 0xF, 1, 1);
}
else
{
// lrr dst, r src
work_reg(insn, insn.Op1, tmp & 0xF, 1, 1);
work_reg(insn, insn.Op2, tmp >> 4, 0, nibble0 != 2);
}
break;
case 0xC2: case 0xC3: case 0xD2: case 0xD3:
tmp = insn.get_next_byte();
insn.itype = (nibble0 == 2) ? Z8_ldc : Z8_ldci;
if ( nibble1 == 0xC )
{
work_reg(insn, insn.Op1, tmp >> 4, 0, nibble0 != 2);
work_reg(insn, insn.Op2, tmp & 0xF, 1, 1);
}
else
{
work_reg(insn, insn.Op1, tmp & 0xF, 1, 1);
work_reg(insn, insn.Op2, tmp >> 4, 0, nibble0 != 2);
}
break;
default:
insn.itype = cmdx2[nibble1];
switch ( nibble0 )
{
case 2: // r1,r2
case 3: // r1,Ir2
tmp = insn.get_next_byte();
work_reg(insn, insn.Op1, tmp >> 4);
work_reg(insn, insn.Op2, tmp & 0xF, 0, nibble0 != 2);
break;
case 4: // R2,R1
case 5: // IR2,R1
dir_reg(insn, insn.Op2, 0, nibble0 == 5);
dir_reg(insn, insn.Op1);
break;
case 6: // R1,IM
case 7: // IR1,IM
dir_reg(insn, insn.Op1, 0, nibble0 == 7);
insn.Op2.value = insn.get_next_byte();
insn.Op2.type = o_imm;
}
switch ( nibble1 )
{
case 0xF: // ld
switch ( nibble0 )
{
case 3: // ld Ir1,r2
insn.Op2.type = o_reg;
insn.Op1.type = o_ind_reg;
insn.itype = Z8_ld;
break;
case 5: // ld R2,IR1
{
op_t tmp_op = insn.Op1;
insn.Op1 = insn.Op2;
insn.Op2 = tmp_op;
insn.itype = Z8_ld;
}
}
break;
case 0xE: // ld
if ( nibble0 != 2 )
insn.itype = Z8_ld;
}
}
}
else // x0..x1
{ /*Z8_srp*/
static const char cmdx01[] =
{
Z8_dec, Z8_rlc, Z8_inc, Z8_jp,
Z8_da, Z8_pop, Z8_com, Z8_push,
Z8_decw, Z8_rl, Z8_incw, Z8_clr,
Z8_rrc, Z8_sra, Z8_rr, Z8_swap
};
insn.itype = cmdx01[nibble1];
switch ( code )
{
case 0x30: // jp @intmem
dir_reg(insn, insn.Op1, 1, 1);
break;
case 0x31: // srp #xx
insn.itype = Z8_srp;
insn.Op1.type = o_imm;
insn.Op1.value = insn.get_next_byte();
insn.Op1.flags |= OF_NUMBER;
break;
default:
dir_reg(insn, insn.Op1, (code == 0x80) || (code == 0xA0), nibble0);
}
}
if ( insn.itype == Z8_null )
return 0; // unknown command
return insn.size;
}

117
idasdk76/module/z8/emu.cpp Normal file
View File

@@ -0,0 +1,117 @@
/*
* Interactive disassembler (IDA).
* Zilog Z8 module
*
*/
#include "z8.hpp"
//----------------------------------------------------------------------
// Calculate the target data address
ea_t z8_t::map_addr(const insn_t &insn, asize_t off, int opnum, bool isdata) const
{
if ( isdata )
{
if ( is_off(get_flags(insn.ea), opnum) )
return get_offbase(insn.ea, opnum) >> 4;
return intmem + off;
}
return map_code_ea(insn, off, opnum);
}
//----------------------------------------------------------------------
void z8_t::handle_operand(const insn_t &insn, const op_t &x, bool isload)
{
switch ( x.type )
{
case o_displ:
case o_imm:
if ( op_adds_xrefs(get_flags(insn.ea), x.n) )
{
int outf = x.type != o_imm ? OOF_ADDR|OOFW_16 : 0;
insn.add_off_drefs(x, dr_O, outf|OOF_SIGNED);
}
break;
case o_mem:
case o_ind_mem:
case o_reg:
case o_ind_reg:
{
ea_t dea;
if ( x.type == o_mem || x.type == o_ind_mem )
{
dea = map_addr(insn, x.addr, x.n, true);
}
else
{
if ( x.reg >= rRR0 )
dea = map_addr(insn, x.reg - rRR0, x.n, true);
else
dea = map_addr(insn, x.reg - rR0, x.n, true);
}
insn.create_op_data(dea, x);
insn.add_dref(dea, x.offb, isload ? dr_R : dr_W);
if ( !has_user_name(get_flags(dea)) && dea > intmem )
{
char buf[10];
int num = dea - intmem;
if ( num < 0x100 )
{
qsnprintf(buf, sizeof(buf), "R%d", num);
}
else if ( num < 0x1000 )
{
qsnprintf(buf, sizeof(buf), "ERF_%X_%d", num >> 8, num & 0xFF);
}
else
{
int reg_no = ((num >> 4) & 0xF0) + (num & 0xF);
int subbank_no = ((num >> 4) & 0xF) + 1;
qsnprintf(buf, sizeof(buf), "R%d_%X", reg_no, subbank_no);
}
set_name(dea, buf, SN_NOCHECK|SN_NOWARN|SN_NODUMMY);
}
}
break;
case o_near:
{
ea_t ea = map_code_ea(insn, x);
int iscall = has_insn_feature(insn.itype, CF_CALL);
insn.add_cref(ea, x.offb, iscall ? fl_CN : fl_JN);
if ( flow && iscall )
flow = func_does_return(ea);
}
break;
}
}
//----------------------------------------------------------------------
int z8_t::z8_emu(const insn_t &insn)
{
uint32 Feature = insn.get_canon_feature(ph);
flow = (Feature & CF_STOP) == 0;
if ( Feature & CF_USE1 ) handle_operand(insn, insn.Op1, true);
if ( Feature & CF_USE2 ) handle_operand(insn, insn.Op2, true);
if ( Feature & CF_JUMP )
remember_problem(PR_JUMP, insn.ea);
if ( Feature & CF_CHG1 ) handle_operand(insn, insn.Op1, false);
if ( Feature & CF_CHG2 ) handle_operand(insn, insn.Op2, false);
if ( flow )
add_cref(insn.ea, insn.ea+insn.size, fl_F);
if ( insn.itype == Z8_srp // Set register pointer
|| (insn.itype == Z8_pop && insn.Op1.type == o_mem && insn.Op1.addr == 0xFD) ) // popping RP
{
// set the RP value
sel_t val = insn.itype == Z8_srp ? (insn.Op1.value & 0xFF) : BADSEL;
split_sreg_range(insn.ea + insn.size, rRp, val, SR_auto, true);
}
return 1;
}

View File

@@ -0,0 +1,67 @@
/*
* Interactive disassembler (IDA).
* Zilog Z8 module
*
*/
#include <ida.hpp>
#include <idp.hpp>
#include "ins.hpp"
const instruc_t Instructions[] =
{
{ "", 0 }, // Unknown Operation
{ "adc", CF_USE2|CF_USE1|CF_CHG1 }, // Add with carry
{ "add", CF_USE2|CF_USE1|CF_CHG1 }, // Add
{ "and", CF_USE2|CF_USE1|CF_CHG1 }, // Logical AND
{ "call", CF_USE1|CF_CALL }, // Call procedure
{ "ccf", 0 }, // Complement carry flag
{ "clr", CF_CHG1 }, // Clear
{ "com", CF_USE1|CF_CHG1 }, // Complement
{ "cp", CF_USE2|CF_USE1 }, // Compare
{ "da", CF_USE1|CF_CHG1 }, // Decimal adjust
{ "dec", CF_USE1|CF_CHG1 }, // Decrement
{ "decw", CF_USE1|CF_CHG1 }, // Decrement word
{ "di", 0 }, // Disable interrupts
{ "djnz", CF_USE2|CF_USE1|CF_CHG1 }, // Decrement and jump if non-zero
{ "ei", 0 }, // Enable interrupts
{ "halt", 0 }, // Enter HALT mode
{ "inc", CF_USE1|CF_CHG1 }, // Increment
{ "incw", CF_USE1|CF_CHG1 }, // Increment word
{ "iret", CF_STOP }, // Return from interrupt
// { "jp", CF_JUMP|CF_USE1|CF_STOP }, // Indirect jump
{ "jp", CF_USE1|CF_STOP }, // Unconditional jump
{ "jp", CF_USE2 }, // Conditional jump
{ "jr", CF_USE1|CF_STOP }, // Relative jump
{ "jr", CF_USE2 }, // Conditional relative jump
{ "ld", CF_USE2|CF_USE1|CF_CHG1 }, // Load data
{ "ldc", CF_USE2|CF_USE1|CF_CHG1 }, // Load constant
{ "ldci", CF_USE2|CF_USE1|CF_CHG1 }, // Load constant with auto-increment
{ "lde", CF_USE2|CF_USE1|CF_CHG1 }, // Load external data
{ "ldei", CF_USE2|CF_USE1|CF_CHG1 }, // Load external data with auto-increment
{ "nop", 0 }, // NOP
{ "or", CF_USE2|CF_USE1|CF_CHG1 }, // Logical OR
{ "pop", CF_CHG1 }, // Pop
{ "push", CF_USE1 }, // Push
{ "rcf", 0 }, // Reset carry flag
{ "ret", CF_STOP }, // Return
{ "rl", CF_SHFT|CF_USE1|CF_CHG1 }, // Rotate left
{ "rlc", CF_SHFT|CF_USE1|CF_CHG1 }, // Rotate left through carry
{ "rr", CF_SHFT|CF_USE1|CF_CHG1 }, // Rotate right
{ "rrc", CF_SHFT|CF_USE1|CF_CHG1 }, // Rotate right through carry
{ "sbc", CF_USE2|CF_USE1|CF_CHG1 }, // Subtract with carry
{ "scf", 0 }, // Set carry flag
{ "sra", CF_SHFT|CF_USE1|CF_CHG1 }, // Shift right arithmetic
{ "srp", CF_USE1 }, // Set register pointer
{ "stop", CF_STOP }, // Enter STOP mode
{ "sub", CF_USE2|CF_USE1|CF_CHG1 }, // Subtract
{ "swap", CF_USE1|CF_CHG1 }, // Swap nibbles
{ "tm", CF_USE2|CF_USE1 }, // Test under mask
{ "tcm", CF_USE2|CF_USE1 }, // Test complement under mask
{ "xor", CF_USE2|CF_USE1|CF_CHG1 }, // Logical EXCLUSIVE OR
{ "wdh", 0 }, // Enable WATCH-DOG in HALT mode
{ "wdt", 0 } // Clear WATCH-DOG timer
};
CASSERT(sizeof(Instructions)/sizeof(Instructions[0]) == Z8_last);

View File

@@ -0,0 +1,69 @@
/*
* Interactive disassembler (IDA).
* Zilog Z8 module
*
*/
#ifndef __INSTRS_HPP
#define __INSTRS_HPP
extern const instruc_t Instructions[];
enum nameNum ENUM_SIZE(uint16)
{
Z8_null = 0, // Unknown Operation
Z8_adc, // Add with carry
Z8_add, // Add
Z8_and, // Logical AND
Z8_call, // Call procedure
Z8_ccf, // Complement carry flag
Z8_clr, // Clear
Z8_com, // Complement
Z8_cp, // Compare
Z8_da, // Decimal adjust
Z8_dec, // Decrement
Z8_decw, // Decrement word
Z8_di, // Disable interrupts
Z8_djnz, // Decrement and jump if non-zero
Z8_ei, // Enable interrupts
Z8_halt, // Enter HALT mode
Z8_inc, // Increment
Z8_incw, // Increment word
Z8_iret, // Return from interrupt
Z8_jp, // Unconditional jump
Z8_jpcond, // Conditional jump
Z8_jr, // Relative jump
Z8_jrcond, // Conditional relative jump
Z8_ld, // Load data
Z8_ldc, // Load constant
Z8_ldci, // Load constant with auto-increment
Z8_lde, // Load external data
Z8_ldei, // Load external data with auto-increment
Z8_nop, // NOP
Z8_or, // Logical OR
Z8_pop, // Pop
Z8_push, // Push
Z8_rcf, // Reset carry flag
Z8_ret, // Return
Z8_rl, // Rotate left
Z8_rlc, // Rotate left through carry
Z8_rr, // Rotate right
Z8_rrc, // Rotate right through carry
Z8_sbc, // Subtract with carry
Z8_scf, // Set carry flag
Z8_sra, // Shift right arithmetic
Z8_srp, // Set register pointer
Z8_stop, // Enter STOP mode
Z8_sub, // Subtract
Z8_swap, // Swap nibbles
Z8_tm, // Test under mask
Z8_tcm, // Test complement under mask
Z8_xor, // Logical EXCLUSIVE OR
Z8_wdh, // Enable WATCH-DOG in HALT mode
Z8_wdt, // Clear WATCH-DOG timer
Z8_last
};
#endif

View File

@@ -0,0 +1,52 @@
PROC=z8
CONFIGS=z8.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)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
../iohandler.hpp ana.cpp ins.hpp z8.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)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)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
../iohandler.hpp emu.cpp ins.hpp z8.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)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
../iohandler.hpp ins.hpp out.cpp z8.hpp
$(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)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
../iohandler.hpp ins.hpp reg.cpp z8.hpp

211
idasdk76/module/z8/out.cpp Normal file
View File

@@ -0,0 +1,211 @@
/*
* Interactive disassembler (IDA).
* Zilog Z8 module
*
*/
#include "z8.hpp"
static const char *const phrases[] =
{
"F", "LT", "LE", "ULE", "OV", "MI", "Z", "C",
"T", "GE", "GT", "UGT", "NOV", "PL", "NZ", "NC"
};
//----------------------------------------------------------------------
inline void z8_t::out_reg(outctx_t &ctx, int rgnum)
{
ctx.out_register(ph.reg_names[rgnum]);
}
//--------------------------------------------------------------------------
void z8_t::z8_header(outctx_t &ctx)
{
ctx.gen_header(GH_PRINT_PROC_ASM_AND_BYTESEX);
}
//--------------------------------------------------------------------------
void z8_t::z8_footer(outctx_t &ctx)
{
ctx.gen_empty_line();
ctx.out_line(ash.end, COLOR_ASMDIR);
ctx.flush_outbuf(DEFAULT_INDENT);
ctx.gen_cmt_line("end of file");
}
//--------------------------------------------------------------------------
//lint -esym(1764, ctx) could be made const
//lint -esym(818, Srange) could be made const
void z8_t::z8_segstart(outctx_t &ctx, segment_t *Srange)
{
qstring sname;
get_visible_segm_name(&sname, Srange);
ctx.gen_cmt_line(COLSTR("segment %s", SCOLOR_AUTOCMT), sname.c_str());
ea_t org = ctx.insn_ea - get_segm_base(Srange);
if ( org != 0 )
{
char buf[MAX_NUMBUF];
btoa(buf, sizeof(buf), org);
ctx.gen_cmt_line("%s %s", ash.origin, buf);
}
}
//--------------------------------------------------------------------------
//lint -esym(818, seg) could be made const
void z8_t::z8_segend(outctx_t &ctx, segment_t *seg)
{
qstring sname;
get_visible_segm_name(&sname, seg);
ctx.gen_cmt_line("end of '%s'", sname.c_str());
}
//----------------------------------------------------------------------
void idaapi out_insn(outctx_t &ctx)
{
ctx.out_mnemonic();
ctx.out_one_operand(0);
if ( ctx.insn.Op2.type != o_void )
{
ctx.out_symbol(',');
ctx.out_char(' ');
ctx.out_one_operand(1);
}
ctx.out_immchar_cmts();
ctx.flush_outbuf();
}
//----------------------------------------------------------------------
bool z8_t::out_opnd(outctx_t &ctx, const op_t &x)
{
uval_t v;
z8_t &pm = *static_cast<z8_t *>(ctx.procmod);
switch ( x.type )
{
case o_imm:
ctx.out_symbol('#');
ctx.out_value(x, OOFW_IMM);
break;
case o_ind_reg:
ctx.out_symbol('@');
// fallthrough
case o_reg:
out_reg(ctx, x.reg);
break;
case o_phrase:
ctx.out_keyword(phrases[x.phrase]);
break;
case o_displ:
ctx.out_value(x, OOF_ADDR | OOFW_16);
ctx.out_symbol('(');
out_reg(ctx, x.reg);
ctx.out_symbol(')');
break;
case o_ind_mem:
ctx.out_symbol('@');
// fallthrough
case o_mem:
case o_near:
v = pm.map_addr(ctx.insn, x.addr, x.n, x.type != o_near);
if ( !ctx.out_name_expr(x, v, x.addr) )
{
const char *name = pm.find_ioport(v);
if ( name != NULL )
{
ctx.out_line(name, COLOR_IMPNAME);
}
else
{
ctx.out_value(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_16);
remember_problem(PR_NONAME, ctx.insn.ea);
}
}
break;
case o_void:
return 0;
default:
warning("out: %a: bad optype %d", ctx.insn.ea, x.type);
}
return 1;
}
//--------------------------------------------------------------------------
static void out_equ(outctx_t &ctx, const char *name, const char *equ, uchar off)
{
ctx.out_line(name, COLOR_DNAME);
ctx.out_char(' ');
ctx.out_line(equ, COLOR_KEYWORD);
ctx.out_char(' ');
ctx.out_tagon(COLOR_NUMBER);
ctx.out_btoa(off);
ctx.out_tagoff(COLOR_NUMBER);
ctx.ctxflags |= CTXF_LABEL_OK;
ctx.flush_outbuf(0x80000000);
}
//--------------------------------------------------------------------------
void z8_t::z8_data(outctx_t &ctx, bool analyze_only)
{
ea_t ea = ctx.insn_ea;
segment_t *s = getseg(ea);
if ( s != NULL && s->type == SEG_IMEM )
{
qstring name;
if ( get_visible_name(&name, ea) > 0 )
out_equ(ctx, name.begin(), ash.a_equ, uint16(ea - get_segm_base(s)));
}
else
{
ctx.out_data(analyze_only);
}
}
//--------------------------------------------------------------------------
//lint -esym(1764, ctx) could be made const
void z8_t::z8_assumes(outctx_t &ctx)
{
ea_t ea = ctx.insn_ea;
segment_t *seg = getseg(ea);
if ( (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 || seg == NULL )
return;
// always show at the start of code segments
bool seg_started = (ea == seg->start_ea) && (seg->type == SEG_CODE);
sreg_range_t sra;
if ( !get_sreg_range(&sra, ea, rRp) )
return;
bool show = sra.start_ea == ea;
if ( show )
{
sreg_range_t prev_sra;
if ( get_prev_sreg_range(&prev_sra, ea, rRp) )
show = sra.val != prev_sra.val;
}
if ( seg_started || show )
{
sel_t rp = sra.val;
if ( rp == BADSEL )
rp = 0;
char num[MAX_NUMBUF];
btoa(num, sizeof(num), rp);
char nbuf[MAXSTR];
qsnprintf(nbuf, sizeof(nbuf), COLSTR(".rp %s", SCOLOR_ASMDIR), num);
ctx.flush_buf(nbuf, DEFAULT_INDENT);
}
}

460
idasdk76/module/z8/reg.cpp Normal file
View File

@@ -0,0 +1,460 @@
/*
* Interactive disassembler (IDA).
* Zilog Z8 module
*
*/
#include "z8.hpp"
#include <diskio.hpp>
int data_id;
//--------------------------------------------------------------------------
static const char *const RegNames[] =
{
"R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
"R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15",
"RR0", "RR1", "RR2", "RR3", "RR4", "RR5", "RR6", "RR7",
"RR8", "RR9", "RR10", "RR11", "RR12", "RR13", "RR14", "RR15",
"cs", "ds", "rp",
};
//----------------------------------------------------------------------
typedef struct
{
int off;
const char *name; //lint !e958 padding is required to align members
const char *cmt;
} entry_t;
static const entry_t entries[] =
{
{ 0, "irq0", "DAV0, IRQ0, Comparator" },
{ 2, "irq1", "DAV1, IRQ1" },
{ 4, "irq2", "DAV2, IRQ2, TIN, Comparator" },
{ 6, "irq3", "IRQ3, Serial in" },
{ 8, "irq4", "T0, Serial out" },
{ 10, "irq5", "T1" },
};
//----------------------------------------------------------------------
static ea_t AdditionalSegment(size_t size, size_t offset, const char *name, const char *sclass, uchar stype)
{
segment_t s;
s.start_ea = free_chunk(0, size, -0xF);
s.end_ea = s.start_ea + size;
s.sel = allocate_selector((s.start_ea-offset) >> 4);
s.type = stype;
add_segm_ex(&s, name, sclass, ADDSEG_NOSREG|ADDSEG_OR_DIE);
return s.start_ea - offset;
}
//----------------------------------------------------------------------
// special handling for areas
bool z8_iohandler_t::area_processing(ea_t start, ea_t end, const char *name, const char *aclass)
{
if ( start >= end )
{
warning("Error in definition of segment %s %s", aclass, name);
return false;
}
if ( strcmp(aclass, "CODE") == 0 )
{
AdditionalSegment(end-start, start, name, aclass, SEG_CODE);
}
else if ( strcmp(aclass, "DATA") == 0 )
{
uchar type = stristr(name, "FSR") != NULL ? SEG_IMEM : SEG_DATA;
AdditionalSegment(end-start, start, name, aclass, type);
}
else
{
return false;
}
return true;
}
//------------------------------------------------------------------
const char *z8_t::find_ioport(uval_t port)
{
const ioport_t *p = ::find_ioport(ioh.ports, port);
return p ? p->name.c_str() : NULL;
}
//----------------------------------------------------------------------
static ea_t specialSeg(sel_t sel, bool make_imem = true)
{
segment_t *s = get_segm_by_sel(sel);
if ( s != NULL )
{
if ( make_imem && s->type != SEG_IMEM )
{
s->type = SEG_IMEM;
s->update();
}
return s->start_ea;
}
return BADADDR;
}
//----------------------------------------------------------------------
void z8_t::setup_data_segment_pointers(void)
{
sel_t sel;
if ( atos(&sel, "INTMEM") || atos(&sel, "RAM") )
intmem = specialSeg(sel);
else
intmem = BADADDR;
}
//----------------------------------------------------------------------
bool z8_t::select_device(int resp_info)
{
char cfgfile[QMAXFILE];
ioh.get_cfg_filename(cfgfile, sizeof(cfgfile));
if ( !choose_ioport_device(&ioh.device, cfgfile) )
{
ioh.device = NONEPROC;
return false;
}
if ( !ioh.display_infotype_dialog(IORESP_ALL, &resp_info, cfgfile) )
return false;
ioh.set_device_name(ioh.device.c_str(), resp_info & ~IORESP_PORT);
setup_data_segment_pointers();
if ( (resp_info & IORESP_PORT) != 0 )
{
if ( intmem == BADADDR )
{
AdditionalSegment(0x1000, 0, "INTMEM", NULL, SEG_IMEM);
setup_data_segment_pointers();
}
for ( int i=0; i < ioh.ports.size(); i++ )
{
const ioport_t &p = ioh.ports[i];
ea_t ea = p.address + intmem;
ea_t oldea = get_name_ea(BADADDR, p.name.c_str());
if ( oldea != ea )
{
if ( oldea != BADADDR )
set_name(oldea, NULL);
del_items(ea, DELIT_EXPAND);
set_name(ea, p.name.c_str(), SN_NODUMMY);
}
if ( !p.cmt.empty() )
set_cmt(ea, p.cmt.c_str(), true);
}
}
return true;
}
//--------------------------------------------------------------------------
const char *z8_t::set_idp_options(
const char *keyword,
int /*value_type*/,
const void * /*value*/,
bool /*idb_loaded*/)
{
if ( keyword != NULL )
return IDPOPT_BADKEY;
select_device(IORESP_PORT|IORESP_INT);
return IDPOPT_OK;
}
//----------------------------------------------------------------------
void z8_t::load_from_idb()
{
ioh.restore_device();
}
//----------------------------------------------------------------------
// This old-style callback only returns the processor module object.
static ssize_t idaapi notify(void *, int msgid, va_list)
{
if ( msgid == processor_t::ev_get_procmod )
return size_t(SET_MODULE_DATA(z8_t));
return 0;
}
//--------------------------------------------------------------------------
ssize_t idaapi z8_t::on_event(ssize_t msgid, va_list va)
{
int code = 0;
switch ( msgid )
{
case processor_t::ev_init:
helper.create(PROCMOD_NODE_NAME);
inf_set_be(true); // MSB first
break;
case processor_t::ev_term:
ioh.ports.clear();
clr_module_data(data_id);
break;
case processor_t::ev_newfile:
{
segment_t *sptr = get_first_seg();
if ( sptr != NULL )
{
if ( sptr->start_ea - get_segm_base(sptr) == 0 )
{
inf_set_start_ea(sptr->start_ea + 0xC);
inf_set_start_ip(0xC);
if ( !inf_like_binary() )
{
// set default entries
for ( int i = 0; i < qnumber(entries); i++ )
{
ea_t ea = sptr->start_ea + entries[i].off;
if ( is_mapped(ea) )
{
create_word(ea, 2);
op_plain_offset(ea, 0, sptr->start_ea);
ea_t ea1 = sptr->start_ea + get_word(ea);
auto_make_proc(ea1);
set_name(ea, entries[i].name, SN_NODUMMY);
set_cmt(sptr->start_ea+get_word(ea), entries[i].cmt, 1);
}
}
}
}
set_segm_class(sptr, "CODE");
}
select_device(IORESP_ALL);
if ( intmem == BADADDR )
{
AdditionalSegment(0x1000, 0, "INTMEM", NULL, SEG_IMEM);
setup_data_segment_pointers();
}
}
break;
case processor_t::ev_oldfile:
load_from_idb();
setup_data_segment_pointers();
break;
case processor_t::ev_creating_segm:
{ // default DS is equal to CS
segment_t *sptr = va_arg(va, segment_t *);
sptr->defsr[rVds-ph.reg_first_sreg] = sptr->sel;
}
break;
case processor_t::ev_out_header:
{
outctx_t *ctx = va_arg(va, outctx_t *);
z8_header(*ctx);
return 1;
}
case processor_t::ev_out_footer:
{
outctx_t *ctx = va_arg(va, outctx_t *);
z8_footer(*ctx);
return 1;
}
case processor_t::ev_out_segstart:
{
outctx_t *ctx = va_arg(va, outctx_t *);
segment_t *seg = va_arg(va, segment_t *);
z8_segstart(*ctx, seg);
return 1;
}
case processor_t::ev_out_segend:
{
outctx_t *ctx = va_arg(va, outctx_t *);
segment_t *seg = va_arg(va, segment_t *);
z8_segend(*ctx, seg);
return 1;
}
case processor_t::ev_out_assumes:
{
outctx_t *ctx = va_arg(va, outctx_t *);
z8_assumes(*ctx);
return 1;
}
case processor_t::ev_ana_insn:
{
insn_t *out = va_arg(va, insn_t *);
return z8_ana(out);
}
case processor_t::ev_emu_insn:
{
const insn_t *insn = va_arg(va, const insn_t *);
return z8_emu(*insn) ? 1 : -1;
}
case processor_t::ev_out_insn:
{
outctx_t *ctx = va_arg(va, outctx_t *);
out_insn(*ctx);
return 1;
}
case processor_t::ev_out_operand:
{
outctx_t *ctx = va_arg(va, outctx_t *);
const op_t *op = va_arg(va, const op_t *);
return out_opnd(*ctx, *op) ? 1 : -1;
}
case processor_t::ev_out_data:
{
outctx_t *ctx = va_arg(va, outctx_t *);
bool analyze_only = va_argi(va, bool);
z8_data(*ctx, analyze_only);
return 1;
}
case processor_t::ev_set_idp_options:
{
const char *keyword = va_arg(va, const char *);
int value_type = va_arg(va, int);
const char *value = va_arg(va, const char *);
const char **errmsg = va_arg(va, const char **);
bool idb_loaded = va_argi(va, bool);
const char *ret = set_idp_options(keyword, value_type, value, idb_loaded);
if ( ret == IDPOPT_OK )
return 1;
if ( errmsg != NULL )
*errmsg = ret;
return -1;
}
default:
break;
}
return code;
}
//--------------------------------------------------------------------------
static const asm_t Z8asm =
{
AS_COLON,
0,
"Zilog Z8 assembler",
0,
NULL,
".org",
".end",
";", // comment string
'\'', // string delimiter
'\0', // char delimiter (no char consts)
"\\\"'", // special symbols in char and string constants
".ascii", // ascii string directive
".byte", // byte directive
".word", // word directive
NULL, // dword (4 bytes)
NULL, // qword (8 bytes)
NULL, // oword (16 bytes)
NULL, // float (4 bytes)
NULL, // double (8 bytes)
NULL, // tbyte (10/12 bytes)
NULL, // packed decimal real
NULL, // arrays (#h,#d,#v,#s(...)
".block %s", // uninited arrays
".equ", // Equ
NULL, // seg prefix
"$",
NULL, // func_header
NULL, // func_footer
NULL, // public
NULL, // weak
NULL, // extrn
NULL, // comm
NULL, // get_type_name
NULL, // align
'(', ')', // lbrace, rbrace
NULL, // mod
NULL, // and
NULL, // or
NULL, // xor
NULL, // not
NULL, // shl
NULL, // shr
NULL, // sizeof
};
static const asm_t *const asms[] = { &Z8asm, NULL };
//--------------------------------------------------------------------------
#define FAMILY "Zilog Z8 series:"
static const char *const shnames[] = { "Z8", NULL };
static const char *const lnames[] = { FAMILY"Zilog Z8 MCU", NULL };
//--------------------------------------------------------------------------
static const uchar retcode[] = { 0xAF }; // ret
static const uchar iretcode[] = { 0xBF }; // iret
static const bytes_t retcodes[] =
{
{ sizeof(retcode), retcode },
{ sizeof(iretcode), iretcode },
{ 0, NULL }
};
//-----------------------------------------------------------------------
// Processor Definition
//-----------------------------------------------------------------------
processor_t LPH =
{
IDP_INTERFACE_VERSION, // version
PLFM_Z8, // id
// flag
PRN_HEX
| PR_RNAMESOK // can use register names for byte names
| PR_SEGTRANS // segment translation is supported (map_code_ea)
| PR_BINMEM // The module creates RAM/ROM segments for binary files
// (the kernel shouldn't ask the user about their sizes and addresses)
| PR_SEGS // has segment registers?
| PR_SGROTHER, // the segment registers don't contain
// the segment selectors, something else
// flag2
PR2_IDP_OPTS, // the module has processor-specific configuration options
8, // 8 bits in a byte for code segments
8, // 8 bits in a byte for other segments
shnames, // short processor names (null term)
lnames, // long processor names (null term)
asms, // array of enabled assemblers
notify, // Various messages:
RegNames, // Register names
qnumber(RegNames), // Number of registers
rVcs,rRp,
1, // size of a segment register
rVcs,rVds,
NULL, // No known code start sequences
retcodes,
0, Z8_last,
Instructions, // instruc
0, // int tbyte_size; -- doesn't exist
{ 0, 0, 0, 0 }, // char real_width[4];
// number of symbols after decimal point
// 2byte float (0-does not exist)
// normal float
// normal double
// long double
Z8_ret, // Icode of return instruction. It is ok to give any of possible return instructions
};

145
idasdk76/module/z8/z8.cfg Normal file
View File

@@ -0,0 +1,145 @@
; The format of the input file:
; each device definition begins with a line like this:
;
; .devicename
;
; after it go the port definitions in this format:
;
; portname address
;
; the bit definitions (optional) are represented like this:
;
; portname.bitname bitnumber
;
; lines beginning with a space are ignored.
; comment lines should be started with ';' character.
;
; the default device is specified at the start of the file
;
; .default device_name
;
; all lines non conforming to the format are passed to the callback function
;
; the processor definition may include the memory configuration.
; the line format is:
;
; area CLASS AREA-NAME START:END
;
; where CLASS is anything, but please use one of CODE, DATA, BSS
; START and END are addresses, the end address is not included
; Interrupt vectors are declared in the following way:
; interrupt NAME ADDRESS COMMENT
.default Z8
.Z8
; http://www.zilog.com/docs/um0016.pdf
; Z8 CPU User Manual
; MEMORY MAP
area CODE code 0x0000:0x10000 ; code segment: up to 64K
area DATA INTMEM 0x0000:0x01000 ; internal RAM/registers
area DATA EXTMEM 0x0000:0x10000 ; external data: up to 64K
; Interrupt and reset vector assignments
interrupt irq0 0x0 DAV0, IRQ0, Comparator
interrupt irq1 0x2 DAV1, IRQ1
interrupt irq2 0x4 DAV2, IRQ2, TIN, Comparator
interrupt irq3 0x6 IRQ3, Serial in
interrupt irq4 0x8 T0, Serial out
interrupt irq5 0xA T1
entry RESET 0xC Reset
; Registers
; use the third nibble for the Expanded Register File (ERF) banks, e.g. 0xF0F for ERF F, register 0F
p0 0x00 Port 0
p1 0x01 Port 1
p2 0x02 Port 2
p3 0x03 Port 3
sio 0xF0 Serial I/O
tmr 0xF1 Timer mode
t1 0xF2 Timer/counter 1
pre1 0xF3 T1 prescaler
t0 0xF4 Timer/counter 0
pre0 0xF5 T0 prescaler
p2m 0xF6 Port 2 mode register
p3m 0xF7 Port 3 mode register
p01m 0xF8 Ports 0-1 mode register
ipr 0xF9 Interrupt priority register
irq 0xFA Interrupt request register
imr 0xFB Interrupt mask register
flags 0xFC Program control flags
rp 0xFD Register pointer
sph 0xFE Stack pointer high byte
spl 0xFF Stack pointer low byte
;Expanded Register Group F
wdtmr 0xF0F Watch Dog Timer
smr 0xF0B Stop Mode Recovery
pcon 0xF00 PCON Register
;Expanded Register Group C
scon 0xC02 SPI Control
rxbuf 0xC01 SPI Tx/Rx Data
scomp 0xC00 SPI Compare
.Z86C93
; http://www.zilog.com/docs/z8/dc2508.pdf
; Z86C93 Product Specification
; MEMORY MAP
area CODE code 0x0000:0x10000 ; code segment: up to 64K
area DATA INTMEM 0x0000:0x01000 ; internal RAM/registers
area DATA EXTMEM 0x0000:0x10000 ; external data: up to 64K
; Interrupt and reset vector assignments
interrupt irq0 0x0 DAV0, P32, T2
interrupt irq1 0x2 P33
interrupt irq2 0x4 DAV2, P31, TIN
interrupt irq3 0x6 P30, Serial in
interrupt irq4 0x8 T0, Serial out
interrupt irq5 0xA T1
entry RESET 0xC Reset
; Registers
; use the third nibble for the Expanded Register File (ERF) banks, e.g. 0xF0F for ERF F, register 0F
p0 0x00 Port 0
p2 0x02 Port 2
p3 0x03 Port 3
sio 0xF0 Serial I/O
tmr 0xF1 Timer mode
t1 0xF2 Timer/counter 1
pre1 0xF3 T1 prescaler
t0 0xF4 Timer/counter 0
pre0 0xF5 T0 prescaler
p2m 0xF6 Port 2 mode register
p3m 0xF7 Port 3 mode register
p01m 0xF8 Ports 0-1 mode register
ipr 0xF9 Interrupt priority register
irq 0xFA Interrupt request register
imr 0xFB Interrupt mask register
flags 0xFC Program control flags
rp 0xFD Register pointer
sph 0xFE Stack pointer high byte
spl 0xFF Stack pointer low byte
;Expanded Register Group E
mreg0 0xE00 Multiply/Divide unit
mreg1 0xE01 Multiply/Divide unit
mreg2 0xE02 Multiply/Divide unit
mreg3 0xE03 Multiply/Divide unit
mreg4 0xE04 Multiply/Divide unit
mreg5 0xE05 Multiply/Divide unit
mdcon 0xE06 Multiply/Divide control register
;Expanded Register Group D
t2tmr 0xD01 T2 timer mode register
t1h 0xD02 Timer/counter 1 high byte
t2pre 0xD03 T2 prescaler register
t0h 0xD04 Timer/counter 0 high byte
t2h 0xD06 Timer/counter 2 high byte
t2l 0xD07 Timer/counter 2 low byte
t2caph 0xD08
t2capl 0xD09

123
idasdk76/module/z8/z8.hpp Normal file
View File

@@ -0,0 +1,123 @@
/*
* .org
* .word
.equ
* .end
* .ascii
* .byte
* .block
*+ IM o_imm 12h
* Ir o_ind_reg @R1
* r o_reg R1
* Irr o_ind_reg @RR1
* RR o_reg RR1
* cond o_phrase
*+ IRR o_ind_mem @INTMEM_12
*+ IR o_ind_mem @INTMEM_12
*+ DA/RA o_near loc_1234
*+ R o_mem INTMEM_12
*+ X o_displ INTMEM_12(R1)
*
* Interactive disassembler (IDA).
* Zilog Z8 module
*
*/
#ifndef _Z8_HPP
#define _Z8_HPP
#include "../idaidp.hpp"
#include "ins.hpp"
#include <segregs.hpp>
#include <diskio.hpp>
#include "../iohandler.hpp"
#define PROCMOD_NAME z8
#define PROCMOD_NODE_NAME "$ Zilog Z8"
//------------------------------------------------------------------
struct z8_iohandler_t : public iohandler_t
{
z8_iohandler_t(netnode &nn) : iohandler_t(nn) {}
virtual bool area_processing(ea_t start, ea_t end, const char *name, const char *aclass) override;
};
struct z8_t : public procmod_t
{
netnode helper;
z8_iohandler_t ioh = z8_iohandler_t(helper);
ea_t intmem = BADADDR; // linear EA of the internal memory/registers segment
bool flow = false;
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
const char *find_ioport(uval_t port);
void setup_data_segment_pointers(void);
bool select_device(int resp_info);
const char *idaapi set_idp_options(
const char *keyword,
int /*value_type*/,
const void * /*value*/,
bool /*idb_loaded*/);
void load_from_idb();
// ana.cpp
int z8_ana(insn_t *insn);
// emu.cpp
int z8_emu(const insn_t &insn);
void handle_operand(const insn_t &insn, const op_t &x, bool isload);
ea_t map_addr(const insn_t &insn, asize_t off, int opnum, bool isdata) const;
// out.cpp
void out_reg(outctx_t &ctx, int rgnum);
bool out_opnd(outctx_t &ctx, const op_t &x);
void z8_header(outctx_t &ctx);
void z8_footer(outctx_t &ctx);
void z8_segstart(outctx_t &ctx, segment_t *seg);
void z8_segend(outctx_t &ctx, segment_t *seg);
void z8_data(outctx_t &ctx, bool analyze_only);
void z8_assumes(outctx_t &ctx);
};
extern int data_id;
//------------------------------------------------------------------------
// customization of insn_t structure:
#define o_ind_mem o_idpspec0 // @intmem
#define o_ind_reg o_idpspec1 // @Rx
//------------------------------------------------------------------------
enum z8_registers
{
rR0, rR1, rR2, rR3, rR4, rR5, rR6, rR7,
rR8, rR9, rR10, rR11, rR12, rR13, rR14, rR15,
rRR0, rRR1, rRR2, rRR3, rRR4, rRR5, rRR6, rRR7,
rRR8, rRR9, rRR10, rRR11, rRR12, rRR13, rRR14, rRR15,
rVcs, rVds, rRp,
};
enum z8_phrases
{
fF, fLT, fLE, fULE, fOV, fMI, fZ, fC,
fTrue, fGE, fGT, fUGT, fNOV, fPL, fNZ, fNC
};
struct predefined_t
{
uchar addr;
const char *name;
const char *cmt;
};
//------------------------------------------------------------------------
inline uint16 get_rp(ea_t ea)
{
sel_t t = get_sreg(ea, rRp);
return t != BADSEL ? t : 0;
}
#endif