update to ida 7.6, add builds
This commit is contained in:
248
idasdk76/module/tms320c5/emu.cpp
Normal file
248
idasdk76/module/tms320c5/emu.cpp
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* 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 "tms.hpp"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static void set_immd_bit(const insn_t &insn)
|
||||
{
|
||||
set_immd(insn.ea);
|
||||
if ( is_defarg0(get_flags(insn.ea)) )
|
||||
return;
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case TMS_and:
|
||||
case TMS_bit:
|
||||
case TMS_bitt:
|
||||
case TMS_bsar:
|
||||
case TMS_cmpr:
|
||||
case TMS_in:
|
||||
case TMS_intr:
|
||||
case TMS_apl2:
|
||||
case TMS_opl2:
|
||||
case TMS_xpl2:
|
||||
case TMS_or:
|
||||
case TMS_rpt:
|
||||
case TMS_xc:
|
||||
case TMS_xor:
|
||||
case TMS_rptz:
|
||||
|
||||
case TMS2_bit:
|
||||
case TMS2_in:
|
||||
case TMS2_out:
|
||||
case TMS2_andk:
|
||||
case TMS2_ork:
|
||||
case TMS2_xork:
|
||||
case TMS2_rptk:
|
||||
op_num(insn.ea, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int tms320c5_t::find_ar(const insn_t &insn, ea_t *res) const
|
||||
{
|
||||
ea_t ea = insn.ea;
|
||||
for ( int i=0; i < get_lookback(); i++ )
|
||||
{
|
||||
ea = prevInstruction(ea);
|
||||
if ( !is_code(get_flags(ea)) )
|
||||
break;
|
||||
ushort _code = (ushort)get_wide_byte(ea);
|
||||
if ( isC2() )
|
||||
{
|
||||
switch ( _code >> 11 )
|
||||
{
|
||||
case 6: // LAR
|
||||
return 0;
|
||||
case 0x18: // LARK
|
||||
*res = map_data_ea(insn, _code & 0xFF);
|
||||
return 1;
|
||||
case 0x1A: // LRLK
|
||||
if ( (_code & 0xF8FF) == 0xD000 )
|
||||
{
|
||||
ushort b = (ushort)get_wide_byte(ea+1);
|
||||
*res = map_data_ea(insn, b);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
switch ( _code >> 11 )
|
||||
{
|
||||
case 0: // Load AR from addressed data
|
||||
return 0; // LAR found, unknown address
|
||||
case 0x16: // Load AR short immediate
|
||||
*res = map_data_ea(insn, _code & 0xFF);
|
||||
return 1;
|
||||
case 0x17: // Load AR long immediate
|
||||
if ( (_code & ~7) == 0xBF08 )
|
||||
{
|
||||
ushort b = (ushort)get_wide_byte(ea+1);
|
||||
*res = map_data_ea(insn, b);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void tms320c5_t::handle_operand(const insn_t &insn, const op_t &x, bool isload)
|
||||
{
|
||||
ea_t ea;
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_phrase: // 2 registers or indirect addressing
|
||||
if ( insn.itype != TMS_mar
|
||||
&& insn.itype != TMS2_mar
|
||||
&& find_ar(insn, &ea) )
|
||||
{
|
||||
goto SET_DREF;
|
||||
}
|
||||
case o_reg:
|
||||
case o_bit:
|
||||
case o_cond:
|
||||
break;
|
||||
case o_imm:
|
||||
{
|
||||
if ( !isload )
|
||||
goto badTouch;
|
||||
set_immd_bit(insn);
|
||||
flags_t F = get_flags(insn.ea);
|
||||
if ( op_adds_xrefs(F, x.n) )
|
||||
insn.add_off_drefs(x, dr_O, is_mpy(insn) ? OOF_SIGNED : 0);
|
||||
}
|
||||
break;
|
||||
case o_mem:
|
||||
ea = map_data_ea(insn, x);
|
||||
SET_DREF:
|
||||
insn.create_op_data(ea, x);
|
||||
insn.add_dref(ea, x.offb, isload ? dr_R : dr_W);
|
||||
if ( x.type == o_mem )
|
||||
{
|
||||
if ( insn.itype == TMS_dmov
|
||||
|| insn.itype == TMS_ltd
|
||||
|| insn.itype == TMS_macd
|
||||
|| insn.itype == TMS_madd
|
||||
|| insn.itype == TMS2_dmov
|
||||
|| insn.itype == TMS2_macd )
|
||||
{
|
||||
insn.add_dref(ea+1, x.offb, dr_W);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case o_near:
|
||||
{
|
||||
ea = map_code_ea(insn, x);
|
||||
if ( insn.itype == TMS_blpd
|
||||
|| insn.itype == TMS_mac
|
||||
|| insn.itype == TMS_macd
|
||||
|| insn.itype == TMS2_blkp
|
||||
|| insn.itype == TMS2_mac
|
||||
|| insn.itype == TMS2_macd )
|
||||
{
|
||||
goto SET_DREF;
|
||||
}
|
||||
ea_t segbase = (ea - x.addr) >> 4;
|
||||
uval_t thisseg = insn.cs;
|
||||
int iscall = has_insn_feature(insn.itype, CF_CALL);
|
||||
if ( insn.itype == TMS_rptb && is_tail(get_flags(ea)) )
|
||||
{
|
||||
// small hack to display end_loop-1 instead of before_end_loop+1
|
||||
ea++;
|
||||
}
|
||||
|
||||
cref_t xtype = iscall
|
||||
? (segbase == thisseg ? fl_CN : fl_CF)
|
||||
: (segbase == thisseg ? fl_JN : fl_JF);
|
||||
insn.add_cref(ea, x.offb, xtype);
|
||||
if ( iscall && !func_does_return(ea) )
|
||||
flow = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
badTouch:
|
||||
warning("%a: %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), x.n, x.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static int isDelayedStop(ushort code)
|
||||
{
|
||||
switch ( code>>12 )
|
||||
{
|
||||
case 7:
|
||||
return (code & 0xFF00u) == 0x7D00u;
|
||||
case 0xB:
|
||||
return code == 0xBE21u;
|
||||
case 0xF:
|
||||
return (code & 0xEFFFu) == 0xEF00u;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool tms320c5_t::can_flow(const insn_t &insn) const
|
||||
{
|
||||
if ( isC2() )
|
||||
return true;
|
||||
flags_t F = get_flags(insn.ea);
|
||||
if ( !is_flow(F) )
|
||||
return true; // no previous instructions
|
||||
ea_t ea = prevInstruction(insn.ea);
|
||||
if ( insn.size == 2 ) // our instruction is long
|
||||
{
|
||||
; // nothing to do
|
||||
}
|
||||
else
|
||||
{ // our instruction short
|
||||
if ( (insn.ea-ea) == 2 ) // prev instruction long
|
||||
return true; // can flow always
|
||||
F = get_flags(ea);
|
||||
if ( !is_code(F) || !is_flow(F) )
|
||||
return true; // no prev instr...
|
||||
ea = prevInstruction(ea);
|
||||
}
|
||||
F = get_flags(ea);
|
||||
return !is_code(F) || !isDelayedStop((ushort)get_wide_byte(ea));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int tms320c5_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_JUMP )
|
||||
remember_problem(PR_JUMP, insn.ea);
|
||||
|
||||
if ( Feature & CF_CHG1 ) handle_operand(insn, insn.Op1, false);
|
||||
if ( Feature & CF_CHG2 ) handle_operand(insn, insn.Op2, false);
|
||||
|
||||
if ( flow && can_flow(insn) )
|
||||
add_cref(insn.ea, insn.ea+insn.size, fl_F);
|
||||
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case TMS_ldp: // change DP register
|
||||
case TMS2_ldp: // change DP register
|
||||
case TMS2_ldpk: // change DP register
|
||||
{
|
||||
uint v = (insn.Op1.type == o_imm) ? uint(insn.Op1.value) : -1u;
|
||||
split_sreg_range(get_item_end(insn.ea), rDP, v, SR_auto);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
Reference in New Issue
Block a user