236 lines
6.5 KiB
C++
236 lines
6.5 KiB
C++
/*
|
|
* 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)
|
|
{
|
|
flags_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;
|
|
}
|