/* * 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 #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,.[BW])/@(d32:.[BW]) x.displtype = dt_movaop1, x.addr, x.szfl - disp_16/disp_32/idx_byte/idx_word x.idxt - type 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