136 lines
3.0 KiB
C++
136 lines
3.0 KiB
C++
|
|
#include "m740.hpp"
|
|
|
|
static void handle_imm(const insn_t &insn, const op_t &op, flags_t F)
|
|
{
|
|
set_immd(insn.ea);
|
|
if ( is_defarg(F, op.n) )
|
|
return;
|
|
bool in_hex = false;
|
|
switch ( insn.itype )
|
|
{
|
|
case m740_and:
|
|
case m740_ora:
|
|
in_hex = true;
|
|
break;
|
|
}
|
|
if ( in_hex )
|
|
op_hex(insn.ea, op.n);
|
|
}
|
|
|
|
void m740_t::handle_operand(const insn_t &insn, const op_t &op)
|
|
{
|
|
flags_t F = get_flags(insn.ea);
|
|
switch ( op.type )
|
|
{
|
|
// code address
|
|
case o_near:
|
|
{
|
|
ea_t ea = to_ea(insn.cs, op.addr);
|
|
cref_t mode = fl_JN;
|
|
if ( insn.itype == m740_jsr )
|
|
{
|
|
if ( !func_does_return(ea) )
|
|
flow = false;
|
|
mode = fl_CN;
|
|
}
|
|
insn.add_cref(ea, op.offb, mode);
|
|
}
|
|
break;
|
|
|
|
// data address
|
|
case o_mem:
|
|
{
|
|
enum dref_t mode = dr_U;
|
|
|
|
if ( is_addr_ind(op) )
|
|
mode = dr_R; /* NOT dr_O */
|
|
else if ( is_addr_read(op) )
|
|
mode = dr_R;
|
|
else if ( is_addr_write(op) )
|
|
mode = dr_W;
|
|
|
|
insn.add_dref(to_ea(insn.cs, op.addr), op.offb, mode);
|
|
insn.create_op_data(op.addr, op);
|
|
}
|
|
break;
|
|
|
|
// immediate
|
|
case o_imm:
|
|
handle_imm(insn, op, F);
|
|
// if the value was converted to an offset, then create a data xref:
|
|
if ( op_adds_xrefs(F, op.n) )
|
|
insn.add_off_drefs(op, dr_O, 0);
|
|
break;
|
|
|
|
// displ
|
|
case o_displ:
|
|
if ( op_adds_xrefs(F, op.n) )
|
|
{
|
|
ea_t ea = insn.add_off_drefs(op, dr_O, OOF_ADDR);
|
|
insn.create_op_data(ea, op);
|
|
}
|
|
break;
|
|
|
|
// reg - do nothing
|
|
case o_reg:
|
|
case o_void:
|
|
break;
|
|
|
|
default:
|
|
INTERR(10022);
|
|
}
|
|
}
|
|
|
|
// emulate an instruction
|
|
int m740_t::emu(const insn_t &insn)
|
|
{
|
|
uint32 feature = insn.get_canon_feature(ph);
|
|
flow = ((feature & CF_STOP) == 0);
|
|
|
|
if ( insn.Op1.type != o_void ) handle_operand(insn, insn.Op1);
|
|
if ( insn.Op2.type != o_void ) handle_operand(insn, insn.Op2);
|
|
if ( insn.Op3.type != o_void ) handle_operand(insn, insn.Op3);
|
|
|
|
/*
|
|
we can't use this code
|
|
|
|
if ( feature & CF_USE1) handle_operand(insn, insn.Op1, 1 );
|
|
if ( feature & CF_USE2) handle_operand(insn, insn.Op2, 1 );
|
|
if ( feature & CF_USE3) handle_operand(insn, insn.Op3, 1 );
|
|
*/
|
|
|
|
// we don't use CF_JUMP
|
|
// if ( feature & CF_JUMP )
|
|
switch ( insn.itype )
|
|
{
|
|
case m740_jmp:
|
|
case m740_jsr:
|
|
if ( insn.Op1.type != o_void && is_addr_ind(insn.Op1) )
|
|
remember_problem(PR_JUMP, insn.ea);
|
|
break;
|
|
}
|
|
|
|
/*
|
|
if ( feature & CF_CHG1) handle_operand(insn, insn.Op1, 0 );
|
|
if ( feature & CF_CHG2) handle_operand(insn, insn.Op2, 0 );
|
|
if ( feature & CF_CHG3) handle_operand(insn, insn.Op3, 0 );
|
|
*/
|
|
|
|
if ( flow )
|
|
{
|
|
// skip the next byte if the current insn is brk
|
|
if ( insn.itype == m740_brk )
|
|
{
|
|
add_cref(insn.ea, insn.ea + insn.size + 1, fl_JN);
|
|
create_byte(insn.ea + insn.size, 1);
|
|
}
|
|
else
|
|
{
|
|
add_cref(insn.ea, insn.ea + insn.size, fl_F);
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|