306 lines
11 KiB
C++
306 lines
11 KiB
C++
/*
|
|
* Interactive disassembler (IDA).
|
|
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
|
* ALL RIGHTS RESERVED.
|
|
* E-mail: ig@datarescue.com
|
|
*
|
|
*
|
|
*/
|
|
|
|
#ifndef _H8_HPP
|
|
#define _H8_HPP
|
|
|
|
#include "../idaidp.hpp"
|
|
#include <diskio.hpp>
|
|
#include "ins.hpp"
|
|
#include "../iohandler.hpp"
|
|
|
|
#define PROCMOD_NAME h8
|
|
#define PROCMOD_NODE_NAME "$ h8"
|
|
|
|
//------------------------------------------------------------------
|
|
// processor types
|
|
|
|
typedef uint16 proctype_t;
|
|
|
|
static const proctype_t none = 0;
|
|
static const proctype_t P300 = 0x0001; // H8/300, H8/300H
|
|
static const proctype_t P2000 = 0x0002; // H8S/2000
|
|
static const proctype_t P2600 = 0x0004; // H8S/2600
|
|
static const proctype_t PSX = 0x0008; // H8SX
|
|
|
|
// assume 'Normal mode' as the default
|
|
static const proctype_t MODE_MASK= 0xF000;
|
|
static const proctype_t MODE_MID = 0x1000; // H8SX
|
|
static const proctype_t MODE_ADV = 0x2000; // H8/300H (!), H8S, H8SX
|
|
static const proctype_t MODE_MAX = 0x3000; // H8SX
|
|
|
|
// submodel
|
|
static const proctype_t SUBM_MASK= 0x0F00;
|
|
static const proctype_t SUBM_TINY= 0x0100; // H8/300H Tiny model
|
|
// full insn set and normal mode
|
|
|
|
static const proctype_t P30A = P300 | MODE_ADV;
|
|
static const proctype_t P26A = P2600 | MODE_ADV;
|
|
|
|
//------------------------------------------------------------------
|
|
#ifdef _MSC_VER
|
|
#define ENUM8BIT : uint8
|
|
#else
|
|
#define ENUM8BIT
|
|
#endif
|
|
enum regnum_t ENUM8BIT
|
|
{
|
|
R0, R1, R2, R3, R4, R5, R6, R7, SP=R7,
|
|
E0, E1, E2, E3, E4, E5, E6, E7,
|
|
R0H, R1H, R2H, R3H, R4H, R5H, R6H, R7H,
|
|
R0L, R1L, R2L, R3L, R4L, R5L, R6L, R7L,
|
|
ER0, ER1, ER2, ER3, ER4, ER5, ER6, ER7,
|
|
// don't change registers order above this line
|
|
MACL, MACH,
|
|
PC,
|
|
CCR, EXR,
|
|
rVcs, rVds, // virtual registers for code and data segments
|
|
VBR, SBR, // base or segment registers
|
|
};
|
|
|
|
//---------------------------------
|
|
// Operand types:
|
|
|
|
/*
|
|
o_reg 1 Register direct
|
|
Rn
|
|
x.reg
|
|
o_phrase 2 Register indirect
|
|
@ERn
|
|
x.phrase contains register number
|
|
x.phtype contains phrase type (normal, post, pre)
|
|
o_displ 3 Register indirect with displacement
|
|
@(d:2,ERn)/@(d:16,ERn)/@(d:32,ERn)
|
|
x.reg, x.addr, disp_16, disp_32, disp_2
|
|
o_displ 4 Index register indirect with displacement
|
|
@(d:16, RnL.B)/@(d:16,Rn.W)/@(d:16,ERn.L)
|
|
@(d:32, RnL.B)/@(d:32,Rn.W)/@(d:32,ERn.L)
|
|
x.displtype = dt_regidx,
|
|
x.reg,
|
|
x.addr - disp_16, disp_32, idx_byte/word/long
|
|
o_phrase 5 Register indirect with post-inc/pre-dec/pre-inc/post-dec
|
|
@ERn+/@-ERn/@+ERn/@ERn-
|
|
o_mem 6 Absolute address
|
|
@aa:8/@aa:16/@aa:24/@aa:32
|
|
x.memtype = @aa:8 ? mem_sbr : mem_direct
|
|
x.addr
|
|
o_imm 7 Immediate
|
|
#x:2/#xx:3/#xx:4/#xx:5/#xx:8/#xx:16/#xx:32
|
|
#1/#2/#4/#8/#16
|
|
x.value
|
|
o_near 8 Program-counter relative
|
|
@(d:8,PC)/@(d:16,PC)
|
|
o_pcidx 9 Program-counter relative with index register
|
|
@(RnL.B,PC)/@(Rn.W,PC)/@(ERn.L,PC)
|
|
x.reg
|
|
o_mem 10 Memory indirect
|
|
@@aa:8
|
|
x.memtype = mem_ind
|
|
x.addr
|
|
o_mem 11 Extended memory indirect
|
|
@@vec:7
|
|
x.memtype = mem_vec7
|
|
x.addr
|
|
o_reglist Register list
|
|
x.reg, x.nregs
|
|
o_displ first operand of MOVA insn
|
|
@(d16,<EA>.[BW])/@(d32:<EA>.[BW])
|
|
x.displtype = dt_movaop1,
|
|
x.addr,
|
|
x.szfl - disp_16/disp_32/idx_byte/idx_word
|
|
x.idxt - <EA> type
|
|
<EA> type:
|
|
o_reg - x.reg EQ to o_regidx
|
|
o_phrase - x.phrase,x.idxdt
|
|
o_displ - x.reg,x.value,x.idxsz,x.idxdt
|
|
o_regidx - x.reg,x.value,x.idxsz,x.idxdt
|
|
o_mem - x.value,x.idsz,x.idxdt
|
|
*/
|
|
|
|
#define o_reglist o_idpspec0
|
|
#define o_pcidx o_idpspec1
|
|
|
|
#define phtype specflag1 // phrase type:
|
|
const int ph_normal = 0; // just simple indirection
|
|
const int ph_pre_dec = 0x10; // -@Rn ^ 3 -> @Rn+
|
|
const int ph_post_inc = 0x13; // @Rn+
|
|
const int ph_pre_inc = 0x11; // +@ERn
|
|
const int ph_post_dec = 0x12; // @ERn-
|
|
|
|
#define displtype specflag1 // displ type:
|
|
const int dt_normal = 0; // Register indirect with displacement
|
|
const int dt_regidx = 1; // Index register indirect with displacement
|
|
const int dt_movaop1 = 2; // first operand of MOVA insn
|
|
|
|
#define szfl specflag2 // various operand size flags
|
|
// index target
|
|
const int idx_byte = 0x01; // .b
|
|
const int idx_word = 0x02; // .w
|
|
const int idx_long = 0x04; // .l
|
|
// size of operand displ
|
|
const int disp_16 = 0x10; // 16bit displacement
|
|
const int disp_24 = 0x20; // 24bit displacement
|
|
const int disp_32 = 0x40; // 32bit displacement
|
|
const int disp_2 = 0x80; // 2bit displacement
|
|
|
|
#define memtype specflag1 // mem type:
|
|
const int mem_direct = 0; // x.addr - direct memory ref
|
|
const int mem_sbr = 1; // SBR based @aa:8
|
|
const int mem_vec7 = 2; // @@vec:7
|
|
const int mem_ind = 3; // @@aa:8
|
|
|
|
#define nregs specflag1 // o_reglist: number of registers
|
|
|
|
// MOVA Op1 store
|
|
#define idxt specflag3 // MOVA: optype_t of index
|
|
#define idxsz specflag4 // MOVA: size of index
|
|
#define idxdt specval // MOVA: index phtype,displtype,memtype
|
|
|
|
//------------------------------------------------------------------
|
|
const uint16 aux_none = 0; // no postfix
|
|
const uint16 aux_byte = 1; // .b postfix
|
|
const uint16 aux_word = 2; // .w postfix
|
|
const uint16 aux_long = 3; // .l postfix
|
|
|
|
//------------------------------------------------------------------
|
|
#define UAS_HEW 0x0001 // HEW assembler
|
|
|
|
//------------------------------------------------------------------
|
|
ea_t calc_mem(const insn_t &insn, ea_t ea); // map virtual to physical ea
|
|
ea_t calc_mem_sbr_based(const insn_t &insn, ea_t ea); // map virtual @aa:8 physical ea
|
|
|
|
void idaapi h8_segend(outctx_t &ctx, segment_t *seg);
|
|
|
|
int idaapi h8_is_align_insn(ea_t ea);
|
|
bool idaapi create_func_frame(func_t *pfn);
|
|
int idaapi is_sp_based(const insn_t &insn, const op_t &x);
|
|
bool idaapi is_return_insn(const insn_t &insn);
|
|
|
|
int is_jump_func(const func_t *pfn, ea_t *jump_target);
|
|
int may_be_func(const insn_t &insn); // can a function start here?
|
|
int is_sane_insn(const insn_t &insn, int nocrefs);
|
|
bool idaapi h8_is_switch(switch_info_t *si, const insn_t &insn);
|
|
|
|
//------------------------------------------------------------------
|
|
struct h8_iohandler_t : public iohandler_t
|
|
{
|
|
h8_iohandler_t(netnode &nn) : iohandler_t(nn) {}
|
|
virtual void get_cfg_filename(char *buf, size_t bufsize) override;
|
|
};
|
|
|
|
struct h8_t : public procmod_t
|
|
{
|
|
netnode helper;
|
|
h8_iohandler_t ioh = h8_iohandler_t(helper);
|
|
proctype_t ptype = none; // contains all bits which correspond
|
|
// to the supported processors set
|
|
char show_sizer = -1;
|
|
uchar code = 0;
|
|
uchar code3 = 0;
|
|
bool flow = false;
|
|
|
|
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
|
|
|
|
inline bool advanced(void) { return (ptype & MODE_MASK) != 0; }
|
|
inline bool is_h8s(void) { return (ptype & (P2000|P2600)) != 0; }
|
|
inline bool is_h8sx(void) { return (ptype & PSX) != 0; }
|
|
inline bool is_tiny(void) { return (ptype & SUBM_TINY) != 0; }
|
|
|
|
inline regnum_t r0(void) { return advanced() ? ER0 : R0; }
|
|
|
|
inline bool is_hew_asm(void) const
|
|
{
|
|
return (ash.uflag & UAS_HEW) != 0;
|
|
}
|
|
|
|
void load_symbols(void);
|
|
const char *find_sym(ea_t address);
|
|
const char *set_idp_options(
|
|
const char *keyword,
|
|
int /*value_type*/,
|
|
const void * /*value*/,
|
|
bool /*idb_loaded*/);
|
|
void set_cpu(int cpuno);
|
|
int get_displ_outf(const op_t &x, flags_t F);
|
|
ea_t trim_ea_branch(ea_t ea) const; // trim address according to proc mode
|
|
void h8_header(outctx_t &ctx);
|
|
void trimaddr(op_t &x);
|
|
void opatHL(op_t &x, op_dtype_t dtyp);
|
|
void opdsp16(insn_t &insn, op_t &x, op_dtype_t dtyp);
|
|
void opdsp32(insn_t &insn, op_t &x, op_dtype_t dtyp);
|
|
bool read_operand(insn_t &insn, op_t &x, ushort flags);
|
|
bool map014(insn_t &insn);
|
|
bool map4(insn_t &insn);
|
|
int ana(insn_t *pinsn);
|
|
int exit_40(insn_t &insn);
|
|
int exit_54_56(insn_t &insn, uint8 rts, uint8 rtsl);
|
|
int exit_59_5D(insn_t &insn, uint16 jump, uint16 branch);
|
|
int exit_7B(insn_t &insn);
|
|
int h8sx_03(insn_t &insn);
|
|
int h8sx_0A(insn_t &insn);
|
|
int h8sx_1A(insn_t &insn);
|
|
int h8sx_6A(insn_t &insn);
|
|
void handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload);
|
|
int h8sx_6B(insn_t &insn);
|
|
int h8sx_78(insn_t &insn);
|
|
int h8sx_79(insn_t &insn);
|
|
int h8sx_7A(insn_t &insn);
|
|
bool h8sx_010D(insn_t &insn);
|
|
bool h8sx_010E(insn_t &insn);
|
|
bool insn_ldc(insn_t &insn, uint8 byte2, regnum_t reg);
|
|
bool h8sx_01_exr(insn_t &insn);
|
|
bool insn_mova(insn_t &insn);
|
|
int insn_mova_reg(insn_t &insn, uint8 opcode, uint8 rs, bool is_reg_equal);
|
|
bool h8sx_01_other(insn_t &insn);
|
|
bool insn_addx_imm(insn_t &insn, op_t &x, uint8 byte2, uint8 byte3, uint16 mask, bool check_byte3);
|
|
bool insn_bra(insn_t &insn, uint8 byte2, uint8 byte3);
|
|
bool insn_bfld_bfst(insn_t &insn, uint8 byte2, uint8 byte3, bool is_bfld);
|
|
bool use_leaf_map(insn_t &insn, const struct map_t *m, uint8 idx);
|
|
bool op_from_byte(insn_t &insn, op_t &x, uint8 byte2);
|
|
bool read_1st_op(insn_t &insn, uint8 byte2, uint8 byte3_hiNi);
|
|
bool op_phrase(const insn_t &insn, op_t &x, uint8 reg, int pht, op_dtype_t dtype=dt_byte);
|
|
bool op_displ_regidx(insn_t &insn, op_t &x, uint8 selector, bool is_32, uint8 reg);
|
|
int emu(const insn_t &insn);
|
|
int h8_get_frame_retsize(const func_t *);
|
|
int h8sx_7C(insn_t &insn);
|
|
int h8sx_7D(insn_t &insn);
|
|
bool h8sx_010_01dd(insn_t &insn, uint16 postfix);
|
|
bool h8sx_ldm(insn_t &insn);
|
|
bool insn_mac(insn_t &insn);
|
|
bool insn_tas(insn_t &insn);
|
|
bool op_phrase_prepost(const insn_t &insn, op_t &x, uint8 reg, uint8 selector);
|
|
bool op_phrase_displ2(const insn_t &insn, op_t &x, uint8 reg, uint8 displ);
|
|
int h8sx_01(insn_t &insn);
|
|
bool h8sx_010_00dd(insn_t &insn);
|
|
int h8sx_7E(insn_t &insn);
|
|
int h8sx_7F(insn_t &insn);
|
|
int unpack_8bit_shift(const map_t *m, insn_t &insn, uint16 itype, uint16 itype2);
|
|
int h8sx_10(insn_t &insn);
|
|
int h8sx_11(insn_t &insn);
|
|
bool h8sx_0108(insn_t &insn);
|
|
bool h8sx_0109_010A(insn_t &insn,op_t ®op, op_t &genop);
|
|
int h8sx_0F(insn_t &insn);
|
|
int h8sx_1F(insn_t &insn);
|
|
void add_code_xref(const insn_t &insn, const op_t &x, ea_t ea);
|
|
|
|
void h8_assumes(outctx_t &ctx);
|
|
void trace_sp(const insn_t &insn) const;
|
|
bool get_op_value(uval_t *value, const insn_t &_insn, const op_t &x) const;
|
|
bool spoils(const insn_t &insn, int reg) const;
|
|
void check_base_reg_change_value(const insn_t &insn) const;
|
|
void h8_segstart(outctx_t &ctx, segment_t *Srange) const;
|
|
void h8_gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const;
|
|
void h8_footer(outctx_t &ctx) const;
|
|
|
|
void load_from_idb();
|
|
};
|
|
extern int data_id;
|
|
|
|
#endif // _H8_HPP
|