Repository URL to install this package:
|
Version:
9.0~240925-3.fc42 ▾
|
/*
* Interactive disassembler (IDA).
* Version 3.05
* Copyright (c) 1990-95 by Ilfak Guilfanov.
* ALL RIGHTS RESERVED.
* FIDO: 2:5020/209
* E-mail: ig@estar.msk.su
*
*/
#include "7900.hpp"
//------------------------------------------------------------------------
// convert to data and add cross-ref
static void DataSet(const insn_t &insn, const op_t &x, ea_t EA, int isload)
{
insn.create_op_data(EA, x);
insn.add_dref(EA, x.offb, isload ? dr_R : dr_W);
}
//----------------------------------------------------------------------
void m7900_t::handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload)
{
flags64_t F = get_flags(insn.ea);
switch ( x.type )
{
case o_phrase:
//remember_problem(PR_JUMP, insn.ea);
case o_void:
case o_reg:
break;
case o_sr:
case o_displ:
set_immd(insn.ea);
if ( !is_forced )
{
ushort addr = ushort(x.addr);
if ( x.type == o_displ )
{
addr += (ushort)insn.ip;
addr += insn.size;
uint32 offb = map_code_ea(insn, addr, x.n);
DataSet(insn, x, offb, isload);
}
else if ( op_adds_xrefs(F, x.n) )
{
insn.add_off_drefs(x, dr_O, 0);
}
}
break;
case o_stk:
case o_imm:
set_immd(insn.ea);
if ( op_adds_xrefs(F, x.n) )
insn.add_off_drefs(x, dr_O, 0);
break;
case o_ab:
if ( x.TypeOper == TAB_INDIRECTED_ABS_X )
{
ea_t ea = to_ea(insn.cs, x.addr);
insn.create_op_data(ea, x.offb, dt_word);
insn.add_dref(ea, x.offb, isload ? dr_R : dr_W);
// get data
uint32 Addr;
Addr = get_word(ea);
Addr = uint32(Addr | (getPG<<16));
insn.add_cref(Addr, 2, fl_JF);
}
else
{
DataSet(insn, x, map_code_ea(insn, x), isload);
}
break;
case o_mem:
// convert to data, add cross ref
switch ( x.TypeOper )
{
case TDIR_DIR_Y:
case TDIR_DIR_X:
case TDIR_DIR:
case TDIR_INDIRECT_DIR:
case TDIR_INDIRECT_DIR_X:
case TDIR_INDIRECT_DIR_Y:
case TDIR_L_INDIRECT_DIR:
case TDIR_L_INDIRECT_DIR_Y:
if ( getDPReg == 1 )
{
insn_t tmp = insn;
op_t &tmpx = tmp.ops[x.n];
tmpx.addr &= 0xFF3F;
DataSet(tmp, tmpx, map_code_ea(tmp, tmpx), isload);
}
else
{
DataSet(insn, x, map_code_ea(insn, x), isload);
}
break;
default:
DataSet(insn, x, map_code_ea(insn, x), isload);
break;
}
break;
case o_near:
{
ea_t ea = to_ea(insn.cs, x.addr);
switch ( insn.itype )
{
case m7900_jsr:
insn.add_cref(ea, x.offb, fl_CN);
if ( !func_does_return(ea) )
flow = false;
break;
case m7900_jsrl:
insn.add_cref(ea, x.offb, fl_CF);
if ( !func_does_return(ea) )
flow = false;
break;
case m7900_jmpl:
insn.add_cref(ea, x.offb, fl_JF);
break;
default:
insn.add_cref(ea, x.offb, fl_JN);
break;
}
}
break;
default:
// warning("%a: %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), x.n, x.type);
break;
}
}
//----------------------------------------------------------------------
static void LDD(const insn_t &ins)
{
static const int DPR[] = { rDPR0, rDPR1, rDPR2, rDPR3 };
for ( int i=0; i < 4; i++ )
if ( GETBIT(ins.Op1.value, i) == 1 )
split_sreg_range(ins.ea+ins.size, DPR[i], ins.ops[1+i].value, SR_auto);
}
//----------------------------------------------------------------------
int m7900_t::emu(const insn_t &insn)
{
// Set PG
split_sreg_range(insn.ea, rPG, ( insn.ea & 0xFF0000 ) >> 16, SR_auto);
uint32 Feature = insn.get_canon_feature(ph);
flow = (Feature & CF_STOP) == 0;
bool flag1 = is_forced_operand(insn.ea, 0);
bool flag2 = is_forced_operand(insn.ea, 1);
bool flag3 = is_forced_operand(insn.ea, 2);
bool flag4 = is_forced_operand(insn.ea, 3);
bool flag5 = is_forced_operand(insn.ea, 4);
if ( Feature & CF_USE1 ) handle_operand(insn, insn.Op1, flag1, true);
if ( Feature & CF_USE2 ) handle_operand(insn, insn.Op2, flag2, true);
if ( Feature & CF_USE3 ) handle_operand(insn, insn.Op3, flag3, true);
if ( Feature & CF_USE4 ) handle_operand(insn, insn.Op4, flag4, true);
if ( Feature & CF_USE5 ) handle_operand(insn, insn.Op5, flag5, true);
if ( Feature & CF_JUMP )
remember_problem(PR_JUMP, insn.ea);
if ( Feature & CF_CHG1 ) handle_operand(insn, insn.Op1, flag1, false);
if ( Feature & CF_CHG2 ) handle_operand(insn, insn.Op2, flag2, false);
if ( Feature & CF_CHG3 ) handle_operand(insn, insn.Op3, flag3, false);
if ( Feature & CF_CHG4 ) handle_operand(insn, insn.Op4, flag4, false);
if ( Feature & CF_CHG5 ) handle_operand(insn, insn.Op5, flag5, false);
if ( flow )
add_cref(insn.ea, insn.ea + insn.size, fl_F);
switch ( insn.itype )
{
case m7900_lddn:
//split_sreg_range(insn.ea + insn.size, GetDPR(), insn.Op1.value, SR_auto);
LDD(insn);
break;
case m7900_ldt:
split_sreg_range(insn.ea + insn.size, rDT, insn.Op1.value, SR_auto);
break;
// clear m flag
case m7900_clm:
split_sreg_range(insn.ea + insn.size, rfM, 0, SR_auto);
break;
// set m flag
case m7900_sem:
split_sreg_range(insn.ea + insn.size, rfM, 1, SR_auto);
break;
// clear processor status
case m7900_clp:
// clear m flag
if ( ((insn.Op1.value & 0x20) >> 5) == 1 )
split_sreg_range(insn.ea + insn.size, rfM, 0, SR_auto);
// clear x flag
if ( ((insn.Op1.value & 0x10) >> 4) == 1 )
split_sreg_range(insn.ea + insn.size, rfX, 0, SR_auto);
break;
// set processor status
case m7900_sep:
// set m flag
if ( ((insn.Op1.value & 0x20) >> 5) == 1 )
split_sreg_range(insn.ea + insn.size, rfM, 1, SR_auto);
// set x flag
if ( ((insn.Op1.value & 0x10) >> 4) == 1 )
split_sreg_range(insn.ea + insn.size, rfX, 1, SR_auto);
break;
// pull processor status from stack
case m7900_plp:
split_sreg_range(insn.ea + insn.size, rfM, BADSEL, SR_auto);
split_sreg_range(insn.ea + insn.size, rfX, BADSEL, SR_auto);
break;
}
return 1;
}