update to ida 7.6, add builds
This commit is contained in:
297
idasdk76/module/f2mc/emu.cpp
Normal file
297
idasdk76/module/f2mc/emu.cpp
Normal file
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "f2mc.hpp"
|
||||
#include <segregs.hpp>
|
||||
#include <frame.hpp>
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static int get_reglist_size(ushort reglist)
|
||||
{
|
||||
int size = 0;
|
||||
for ( int i = 0; i < 8; i++ )
|
||||
if ( (reglist >> i) & 1 )
|
||||
size++;
|
||||
return size;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static bool is_bank(const op_t &op)
|
||||
{
|
||||
if ( op.type != o_reg )
|
||||
return false;
|
||||
|
||||
return op.reg == DTB
|
||||
|| op.reg == ADB
|
||||
|| op.reg == SSB
|
||||
|| op.reg == USB
|
||||
|| op.reg == DPR
|
||||
|| op.reg == PCB;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void process_imm(const insn_t &insn, const op_t &x)
|
||||
{
|
||||
set_immd(insn.ea);
|
||||
|
||||
if ( op_adds_xrefs(get_flags(insn.ea), x.n) )
|
||||
insn.add_off_drefs(x, dr_O, calc_outf(x));
|
||||
|
||||
if ( is_defarg(get_flags(insn.ea), x.n) )
|
||||
return; // if already defined by user
|
||||
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case F2MC_add:
|
||||
case F2MC_addl:
|
||||
case F2MC_addsp:
|
||||
case F2MC_addw2:
|
||||
case F2MC_and:
|
||||
case F2MC_andw2:
|
||||
case F2MC_callv:
|
||||
case F2MC_cbne:
|
||||
case F2MC_cmp2:
|
||||
case F2MC_cmpl:
|
||||
case F2MC_cmpw2:
|
||||
case F2MC_cwbne:
|
||||
case F2MC_int:
|
||||
case F2MC_link:
|
||||
case F2MC_mov:
|
||||
case F2MC_movl:
|
||||
case F2MC_movn:
|
||||
case F2MC_movw:
|
||||
case F2MC_movx:
|
||||
case F2MC_or:
|
||||
case F2MC_orw2:
|
||||
case F2MC_sub:
|
||||
case F2MC_subl:
|
||||
case F2MC_subw2:
|
||||
case F2MC_xor:
|
||||
case F2MC_xorw2:
|
||||
op_num(insn.ea, x.n);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void f2mc_t::handle_operand(const insn_t &insn, const op_t &x, bool use)
|
||||
{
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_reg:
|
||||
case o_phrase:
|
||||
case o_reglist:
|
||||
return;
|
||||
|
||||
case o_near:
|
||||
case o_far:
|
||||
{
|
||||
cref_t ftype = fl_JN;
|
||||
ea_t ea = x.addr;
|
||||
// 24-bit (far) operands store the full address.
|
||||
// so this calculation is needed only for near jumps/calls
|
||||
if ( x.type == o_near )
|
||||
ea = calc_code_mem(insn, x.addr);
|
||||
|
||||
if ( has_insn_feature(insn.itype, CF_CALL) )
|
||||
{
|
||||
if ( !func_does_return(ea) )
|
||||
flow = false;
|
||||
ftype = fl_CN;
|
||||
}
|
||||
insn.add_cref(ea, x.offb, ftype);
|
||||
}
|
||||
break;
|
||||
|
||||
case o_imm:
|
||||
QASSERT(10102, use);
|
||||
process_imm(insn, x);
|
||||
break;
|
||||
|
||||
case o_mem:
|
||||
{
|
||||
ea_t ea = calc_data_mem(x.addr);
|
||||
insn.add_dref(ea, x.offb, use ? dr_R : dr_W);
|
||||
insn.create_op_data(ea, x);
|
||||
}
|
||||
break;
|
||||
case o_displ:
|
||||
process_imm(insn, x);
|
||||
if ( may_create_stkvars() && x.reg == RW3 )
|
||||
{
|
||||
func_t *pfn = get_func(insn.ea);
|
||||
if ( pfn != NULL
|
||||
&& (pfn->flags & FUNC_FRAME) != 0
|
||||
&& insn.create_stkvar(x, x.addr, STKVAR_VALID_SIZE) )
|
||||
{
|
||||
op_stkvar(insn.ea, x.n);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
warning("%a: %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), x.n, x.type);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline bool add_stkpnt(func_t *pfn, sval_t delta, const insn_t &insn)
|
||||
{
|
||||
return add_auto_stkpnt(pfn, insn.ea + insn.size, delta);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void trace_sp(const insn_t &insn)
|
||||
{
|
||||
func_t *pfn = get_func(insn.ea);
|
||||
if ( pfn == NULL )
|
||||
return;
|
||||
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case F2MC_int:
|
||||
case F2MC_intp:
|
||||
case F2MC_int9:
|
||||
add_stkpnt(pfn, -6*2, insn);
|
||||
break;
|
||||
case F2MC_reti:
|
||||
add_stkpnt(pfn, 6*2, insn);
|
||||
break;
|
||||
case F2MC_link:
|
||||
add_stkpnt(pfn, -2-insn.Op1.value, insn);
|
||||
break;
|
||||
case F2MC_unlink:
|
||||
add_stkpnt(pfn, -get_spd(pfn, insn.ea), insn);
|
||||
break;
|
||||
case F2MC_ret:
|
||||
add_stkpnt(pfn, 2, insn);
|
||||
break;
|
||||
case F2MC_retp:
|
||||
add_stkpnt(pfn, 2*2, insn);
|
||||
break;
|
||||
case F2MC_pushw:
|
||||
if ( insn.Op1.type == o_reglist )
|
||||
add_stkpnt(pfn, -get_reglist_size(insn.Op1.reg)*2, insn);
|
||||
else
|
||||
add_stkpnt(pfn, -2, insn);
|
||||
break;
|
||||
case F2MC_popw:
|
||||
if ( insn.Op1.type == o_reglist )
|
||||
add_stkpnt(pfn, get_reglist_size(insn.Op1.reg)*2, insn);
|
||||
else
|
||||
add_stkpnt(pfn, 2, insn);
|
||||
break;
|
||||
case F2MC_addsp:
|
||||
add_stkpnt(pfn, insn.Op1.value, insn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
int f2mc_t::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_USE3 ) handle_operand(insn, insn.Op3, true);
|
||||
|
||||
if ( feature & CF_CHG1 ) handle_operand(insn, insn.Op1, false);
|
||||
if ( feature & CF_CHG2 ) handle_operand(insn, insn.Op2, false);
|
||||
if ( feature & CF_CHG3 ) handle_operand(insn, insn.Op3, false);
|
||||
|
||||
// check for CCR changes
|
||||
if ( insn.Op1.type == o_reg && insn.Op1.reg == CCR )
|
||||
{
|
||||
op_bin(insn.ea, 1);
|
||||
|
||||
sel_t ccr = get_sreg(insn.ea, CCR);
|
||||
if ( ccr == BADSEL )
|
||||
ccr = 0;
|
||||
|
||||
if ( insn.itype == F2MC_and )
|
||||
ccr &= insn.Op2.value; // and ccr,imm8
|
||||
else if ( insn.itype == F2MC_or )
|
||||
ccr |= insn.Op2.value; // or ccr,imm8
|
||||
split_sreg_range(get_item_end(insn.ea), CCR, ccr, SR_auto);
|
||||
}
|
||||
|
||||
|
||||
// check for DTB,ADB,SSB,USB,DPR changes
|
||||
if ( insn.itype == F2MC_mov && is_bank(insn.Op1)
|
||||
&& insn.Op2.type == o_reg && insn.Op2.reg == A ) // mov dtb|adb|ssb|usb|dpr,a
|
||||
{
|
||||
sel_t bank = BADSEL;
|
||||
insn_t l;
|
||||
if ( decode_prev_insn(&l, insn.ea) != BADADDR && l.itype == F2MC_mov
|
||||
&& l.Op1.type == o_reg && l.Op1.reg == A )
|
||||
{
|
||||
if ( l.Op2.type == o_imm ) // mov a,imm8
|
||||
bank = l.Op2.value;
|
||||
else if ( is_bank(l.Op2) ) // mov a,dtb|adb|ssb|usb|dpr|pcb
|
||||
{
|
||||
bank = get_sreg(l.ea, l.Op2.reg);
|
||||
if ( bank == BADSEL )
|
||||
bank = 0;
|
||||
}
|
||||
}
|
||||
if ( bank != BADSEL )
|
||||
split_sreg_range(get_item_end(insn.ea), insn.Op1.reg, bank, SR_auto);
|
||||
}
|
||||
|
||||
|
||||
// determine if the next instruction should be executed
|
||||
if ( segtype(insn.ea) == SEG_XTRN )
|
||||
flow = false;
|
||||
if ( flow )
|
||||
add_cref(insn.ea, insn.ea + insn.size, fl_F);
|
||||
|
||||
if ( may_trace_sp() )
|
||||
{
|
||||
if ( !flow )
|
||||
recalc_spd(insn.ea); // recalculate SP register for the next insn
|
||||
else
|
||||
trace_sp(insn);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool idaapi create_func_frame(func_t *pfn)
|
||||
{
|
||||
if ( pfn != NULL )
|
||||
{
|
||||
if ( pfn->frame == BADNODE )
|
||||
{
|
||||
ea_t ea = pfn->start_ea;
|
||||
if ( ea + 4 < pfn->end_ea ) // minimum 2+1+1 bytes needed
|
||||
{
|
||||
insn_t insn;
|
||||
decode_insn(&insn, ea);
|
||||
if ( insn.itype == F2MC_link )
|
||||
{
|
||||
size_t localsize = (size_t)insn.Op1.value;
|
||||
ushort regsize = 2;
|
||||
decode_insn(&insn, ea + 2);
|
||||
pfn->flags |= FUNC_FRAME;
|
||||
return add_frame(pfn, localsize, regsize, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int idaapi is_sp_based(const insn_t &, const op_t &)
|
||||
{
|
||||
return OP_SP_ADD | OP_FP_BASED;
|
||||
}
|
||||
Reference in New Issue
Block a user