update to ida 7.6, add builds
This commit is contained in:
1450
idasdk76/module/tms320c54/ana.cpp
Normal file
1450
idasdk76/module/tms320c54/ana.cpp
Normal file
File diff suppressed because it is too large
Load Diff
435
idasdk76/module/tms320c54/emu.cpp
Normal file
435
idasdk76/module/tms320c54/emu.cpp
Normal file
@@ -0,0 +1,435 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tms320c54.hpp"
|
||||
#include <segregs.hpp>
|
||||
#include <frame.hpp>
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
ea_t calc_code_mem(const insn_t &insn, ea_t ea, bool is_near)
|
||||
{
|
||||
ea_t rv;
|
||||
if ( is_near )
|
||||
{
|
||||
sel_t xpc = get_sreg(insn.ea, XPC);
|
||||
if ( xpc == BADSEL )
|
||||
xpc = 0;
|
||||
rv = ((xpc & 0x7F) << 16) | (ea & 0xFFFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = to_ea(insn.cs, ea);
|
||||
}
|
||||
return use_mapping(rv);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
ea_t tms320c54_t::calc_data_mem(const insn_t &insn, ea_t ea, bool is_mem) const
|
||||
{
|
||||
ea_t rv;
|
||||
if ( is_mem )
|
||||
{
|
||||
sel_t dp = get_sreg(insn.ea, DP);
|
||||
if ( dp == BADSEL )
|
||||
return BADSEL;
|
||||
rv = ((dp & 0x1FF) << 7) | (ea & 0x7F);
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = ea;
|
||||
}
|
||||
rv += dataseg;
|
||||
return use_mapping(rv);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
regnum_t tms320c54_t::get_mapped_register(ea_t ea) const
|
||||
{
|
||||
if ( idpflags & TMS320C54_MMR )
|
||||
{
|
||||
switch ( ea-dataseg )
|
||||
{
|
||||
case 0x00: return IMR;
|
||||
case 0x01: return IFR;
|
||||
case 0x06: return ST0;
|
||||
case 0x07: return ST1;
|
||||
case 0x08: return AL;
|
||||
case 0x09: return AH;
|
||||
case 0x0A: return AG;
|
||||
case 0x0B: return BL;
|
||||
case 0x0C: return BH;
|
||||
case 0x0D: return BG;
|
||||
case 0x0E: return T;
|
||||
case 0x0F: return TRN;
|
||||
case 0x10: return AR0;
|
||||
case 0x11: return AR1;
|
||||
case 0x12: return AR2;
|
||||
case 0x13: return AR3;
|
||||
case 0x14: return AR4;
|
||||
case 0x15: return AR5;
|
||||
case 0x16: return AR6;
|
||||
case 0x17: return AR7;
|
||||
case 0x18: return SP;
|
||||
case 0x19: return BK;
|
||||
case 0x1A: return BRC;
|
||||
case 0x1B: return RSA;
|
||||
case 0x1C: return REA;
|
||||
case 0x1D: return PMST;
|
||||
case 0x1E: return XPC;
|
||||
default: return rnone;
|
||||
}
|
||||
}
|
||||
else
|
||||
return rnone;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void process_imm(const insn_t &insn, const op_t &x, flags_t F)
|
||||
{
|
||||
set_immd(insn.ea);
|
||||
if ( is_defarg(F, x.n) )
|
||||
return; // if already defined by user
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case TMS320C54_cmpm:
|
||||
case TMS320C54_bitf:
|
||||
case TMS320C54_andm:
|
||||
case TMS320C54_orm:
|
||||
case TMS320C54_xorm:
|
||||
case TMS320C54_addm:
|
||||
case TMS320C54_st:
|
||||
case TMS320C54_stm:
|
||||
case TMS320C54_rpt:
|
||||
case TMS320C54_ld3:
|
||||
case TMS320C54_mpy2:
|
||||
case TMS320C54_rptz:
|
||||
case TMS320C54_add3:
|
||||
case TMS320C54_sub3:
|
||||
case TMS320C54_and3:
|
||||
case TMS320C54_or3:
|
||||
case TMS320C54_xor3:
|
||||
case TMS320C54_mac2:
|
||||
op_num(insn.ea, x.n);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void tms320c54_t::handle_operand(const insn_t &insn, const op_t &x, flags_t F, bool use)
|
||||
{
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_bit:
|
||||
case o_reg:
|
||||
case o_cond8:
|
||||
case o_cond2:
|
||||
return;
|
||||
|
||||
case o_near:
|
||||
case o_far:
|
||||
{
|
||||
if ( insn.itype != TMS320C54_rptb && insn.itype != TMS320C54_rptbd )
|
||||
{
|
||||
cref_t ftype = fl_JN;
|
||||
ea_t ea = calc_code_mem(insn, x.addr, x.type == o_near);
|
||||
if ( has_insn_feature(insn.itype, CF_CALL) )
|
||||
{
|
||||
if ( !func_does_return(ea) )
|
||||
flow = false;
|
||||
ftype = fl_CN;
|
||||
}
|
||||
#ifndef TMS320C54_NO_NAME_NO_REF
|
||||
if ( x.dtype == dt_byte )
|
||||
insn.add_dref(ea, x.offb, dr_R);
|
||||
else
|
||||
insn.add_cref(ea, x.offb, ftype);
|
||||
#endif
|
||||
}
|
||||
#ifndef TMS320C54_NO_NAME_NO_REF
|
||||
else // evaluate RPTB[D] loops as dref
|
||||
insn.add_dref(calc_code_mem(insn, x.addr), x.offb, dr_I);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case o_imm:
|
||||
QASSERT(10113, use);
|
||||
process_imm(insn, x, F);
|
||||
#ifndef TMS320C54_NO_NAME_NO_REF
|
||||
if ( op_adds_xrefs(F, x.n) )
|
||||
insn.add_off_drefs(x, dr_O, x.Signed ? OOF_SIGNED : 0);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case o_mem:
|
||||
case o_farmem:
|
||||
case o_mmr:
|
||||
{
|
||||
ea_t ea = calc_data_mem(insn, x.addr, x.type == o_mem);
|
||||
if ( ea != BADADDR )
|
||||
{
|
||||
#ifndef TMS320C54_NO_NAME_NO_REF
|
||||
insn.add_dref(ea, x.offb, use ? dr_R : dr_W);
|
||||
#endif
|
||||
insn.create_op_data(ea, x);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case o_local: // local variables
|
||||
if ( may_create_stkvars()
|
||||
&& (get_func(insn.ea) != NULL)
|
||||
&& insn.create_stkvar(x, x.addr, STKVAR_VALID_SIZE) )
|
||||
{
|
||||
op_stkvar(insn.ea, x.n);
|
||||
}
|
||||
break;
|
||||
|
||||
case o_displ:
|
||||
set_immd(insn.ea);
|
||||
break;
|
||||
|
||||
default:
|
||||
warning("interr: emu2 address:%a operand:%d type:%d", insn.ea, x.n, x.type);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// is the previous instruction a delayed jump ?
|
||||
//
|
||||
// The following array shows all delayed instructions (xxx[D])
|
||||
// who are required to always stop.
|
||||
//
|
||||
// Z = 1 : delay instruction bit
|
||||
//
|
||||
// BRANCH INSTRUCTIONS
|
||||
//
|
||||
// TMS320C54_bd, // Branch Unconditionally 1111 00Z0 0111 0011 16-bit constant B[D] pmad
|
||||
// TMS320C54_baccd, // Branch to Location Specified by Accumulator 1111 01ZS 1110 0010 BACC[D] src
|
||||
// TMS320C54_fbd, // Far Branch Unconditionally 1111 10Z0 1 7bit constant=pmad(22-16) 16-bit constant=pmad(15-0) FB[D] extpmad
|
||||
// TMS320C54_fbaccd, // Far Branch to Location Specified by Accumulator 1111 01ZS 1110 0110 FBACC[D] src
|
||||
//
|
||||
// RETURN INSTRUCTIONS
|
||||
//
|
||||
// TMS320C54_fretd, // Far Return 1111 01Z0 1110 0100 FRET[D]
|
||||
// TMS320C54_freted, // Enable Interrupts and Far Return From Interrupt 1111 01Z0 1110 0101 FRETE[D]
|
||||
// TMS320C54_retd, // Return 1111 11Z0 0000 0000 RET[D]
|
||||
// TMS320C54_reted, // Enable Interrupts and Return From Interrupt 1111 01Z0 1110 1011 RETE[D]
|
||||
// TMS320C54_retfd, // Enable Interrupts and Fast Return From Interrupt 1111 01Z0 1001 1011 RETF[D]
|
||||
|
||||
static bool delayed_stop(const insn_t &insn, flags_t F)
|
||||
{
|
||||
if ( !is_flow(F) )
|
||||
return false;
|
||||
|
||||
if ( insn.size == 0 || insn.size > 2 )
|
||||
return false;
|
||||
|
||||
int sub = 2 - insn.size; // backward offset to skip the previous 1-word instruction in the case of 2 consecutive 1-word instructions
|
||||
|
||||
// first, we analyze 1-word instructions
|
||||
ea_t ea = insn.ea - sub - 1;
|
||||
if ( is_code(get_flags(ea)) )
|
||||
{
|
||||
int code = get_wide_byte(ea); // get the instruction word
|
||||
switch ( code )
|
||||
{
|
||||
case 0xF6E2: // TMS320C54_baccd, // Branch to Location Specified by Accumulator 1111 01ZS 1110 0010 BACC[D] src
|
||||
case 0xF7E2:
|
||||
case 0xF6E6: // TMS320C54_fbaccd, // Far Branch to Location Specified by Accumulator 1111 01ZS 1110 0110 FBACC[D] src
|
||||
case 0xF7E6:
|
||||
case 0xF6E4: // TMS320C54_fretd, // Far Return 1111 01Z0 1110 0100 FRET[D]
|
||||
case 0xF6E5: // TMS320C54_freted, // Enable Interrupts and Far Return From Interrupt 1111 01Z0 1110 0101 FRETE[D]
|
||||
case 0xFE00: // TMS320C54_retd, // Return 1111 11Z0 0000 0000 RET[D]
|
||||
case 0xF6EB: // TMS320C54_reted, // Enable Interrupts and Return From Interrupt 1111 01Z0 1110 1011 RETE[D]
|
||||
case 0xF69B: // TMS320C54_retfd, // Enable Interrupts and Fast Return From Interrupt 1111 01Z0 1001 1011 RETF[D]
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// else, we analyze 2-word instructions
|
||||
ea = insn.ea - sub - 2;
|
||||
if ( is_code(get_flags(ea)) )
|
||||
{
|
||||
int code = get_wide_byte(ea); // get the first instruction word
|
||||
if ( code == 0xF273 // TMS320C54_bd, // Branch Unconditionally 1111 00Z0 0111 0011 16-bit constant B[D] pmad
|
||||
|| (code & 0xFF80) == 0xFA80 ) // TMS320C54_fbd, // Far Branch Unconditionally 1111 10Z0 1 7bit constant=pmad(22-16) 16-bit constant=pmad(15-0) FB[D] extpmad
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool is_basic_block_end(const insn_t &insn)
|
||||
{
|
||||
flags_t F = get_flags(insn.ea);
|
||||
if ( delayed_stop(insn, F) )
|
||||
return true;
|
||||
return !is_flow(get_flags(insn.ea+insn.size));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool add_stkpnt(const insn_t &insn, sval_t delta)
|
||||
{
|
||||
func_t *pfn = get_func(insn.ea);
|
||||
if ( pfn == NULL )
|
||||
return false;
|
||||
|
||||
return add_auto_stkpnt(pfn, insn.ea+insn.size, delta);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void trace_sp(const insn_t &insn)
|
||||
{
|
||||
// trace SP changes
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case TMS320C54_fret:
|
||||
case TMS320C54_fretd:
|
||||
case TMS320C54_frete:
|
||||
case TMS320C54_freted:
|
||||
add_stkpnt(insn, 2);
|
||||
break;
|
||||
case TMS320C54_ret:
|
||||
case TMS320C54_retd:
|
||||
case TMS320C54_rete:
|
||||
case TMS320C54_reted:
|
||||
case TMS320C54_retf:
|
||||
case TMS320C54_retfd:
|
||||
add_stkpnt(insn, 1);
|
||||
break;
|
||||
case TMS320C54_frame:
|
||||
add_stkpnt(insn, insn.Op1.value);
|
||||
break;
|
||||
case TMS320C54_popd:
|
||||
case TMS320C54_popm:
|
||||
add_stkpnt(insn, 1);
|
||||
break;
|
||||
case TMS320C54_pshd:
|
||||
case TMS320C54_pshm:
|
||||
add_stkpnt(insn, -1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int tms320c54_t::emu(const insn_t &insn)
|
||||
{
|
||||
uint32 feature = insn.get_canon_feature(ph);
|
||||
flow = (feature & CF_STOP) == 0;
|
||||
|
||||
flags_t F = get_flags(insn.ea);
|
||||
if ( feature & CF_USE1 ) handle_operand(insn, insn.Op1, F, true);
|
||||
if ( feature & CF_USE2 ) handle_operand(insn, insn.Op2, F, true);
|
||||
if ( feature & CF_USE3 ) handle_operand(insn, insn.Op3, F, true);
|
||||
|
||||
if ( feature & CF_CHG1 ) handle_operand(insn, insn.Op1, F, false);
|
||||
if ( feature & CF_CHG2 ) handle_operand(insn, insn.Op2, F, false);
|
||||
if ( feature & CF_CHG3 ) handle_operand(insn, insn.Op3, F, false);
|
||||
|
||||
// check for CPL changes
|
||||
if ( (insn.itype == TMS320C54_rsbx1 || insn.itype == TMS320C54_ssbx1)
|
||||
&& insn.Op1.type == o_reg && insn.Op1.reg == CPL )
|
||||
{
|
||||
int value = insn.itype == TMS320C54_rsbx1 ? 0 : 1;
|
||||
split_sreg_range(get_item_end(insn.ea), CPL, value, SR_auto);
|
||||
}
|
||||
|
||||
// check for DP changes
|
||||
if ( insn.itype == TMS320C54_ld2
|
||||
&& insn.Op1.type == o_imm
|
||||
&& insn.Op1.dtype == dt_byte
|
||||
&& insn.Op2.type == o_reg
|
||||
&& insn.Op2.reg == DP )
|
||||
{
|
||||
split_sreg_range(get_item_end(insn.ea), DP, insn.Op1.value & 0x1FF, SR_auto);
|
||||
}
|
||||
|
||||
// determine if the next instruction should be executed
|
||||
if ( segtype(insn.ea) == SEG_XTRN )
|
||||
flow = false;
|
||||
if ( flow && delayed_stop(insn, F) )
|
||||
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 tms320c54_t::create_func_frame(func_t *pfn) const
|
||||
{
|
||||
if ( pfn != NULL )
|
||||
{
|
||||
if ( pfn->frame == BADNODE )
|
||||
{
|
||||
insn_t insn;
|
||||
int regsize = 0;
|
||||
ea_t ea = pfn->start_ea;
|
||||
while ( ea < pfn->end_ea ) // check for register pushs
|
||||
{
|
||||
if ( decode_insn(&insn, ea) < 1 )
|
||||
break;
|
||||
if ( insn.itype != TMS320C54_pshm )
|
||||
break;
|
||||
if ( insn.Op1.type != o_mem && insn.Op1.type != o_mmr )
|
||||
break;
|
||||
if ( get_mapped_register(insn.Op1.addr) == rnone )
|
||||
break;
|
||||
regsize++;
|
||||
ea += insn.size;
|
||||
}
|
||||
int localsize = 0;
|
||||
while ( ea < pfn->end_ea ) // check for frame creation
|
||||
{
|
||||
if ( insn.itype == TMS320C54_frame && insn.Op1.type == o_imm )
|
||||
{
|
||||
localsize = -(int)insn.Op1.value;
|
||||
break;
|
||||
}
|
||||
ea += insn.size;
|
||||
if ( decode_insn(&insn, ea) < 1 )
|
||||
break;
|
||||
}
|
||||
add_frame(pfn, localsize+regsize, 0, 0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int idaapi tms_get_frame_retsize(const func_t * /*pfn*/)
|
||||
{
|
||||
return 1; // 1 'byte' for the return address
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int idaapi is_align_insn(ea_t ea)
|
||||
{
|
||||
insn_t insn;
|
||||
if ( decode_insn(&insn, ea) < 1 )
|
||||
return 0;
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case TMS320C54_nop:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return insn.size;
|
||||
}
|
||||
|
||||
307
idasdk76/module/tms320c54/ins.cpp
Normal file
307
idasdk76/module/tms320c54/ins.cpp
Normal file
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tms320c54.hpp"
|
||||
|
||||
const instruc_t Instructions[] =
|
||||
{
|
||||
|
||||
{ "", 0 }, // Unknown Operation
|
||||
|
||||
// ARITHMETIC OPERATIONS
|
||||
|
||||
// ADD INSTRUCTIONS
|
||||
|
||||
{ "add", CF_CHG1 }, // Add to Accumulator
|
||||
{ "add", CF_USE1|CF_CHG2 }, // Add to Accumulator
|
||||
{ "add", CF_USE1|CF_USE2|CF_CHG3 }, // Add to Accumulator
|
||||
{ "addc", CF_USE1|CF_CHG2 }, // Add to Accumulator With Carry
|
||||
{ "addm", CF_USE1|CF_CHG2 }, // Add Long-Immediate Value to Memory
|
||||
{ "adds", CF_USE1|CF_CHG2 }, // Add to Accumulator With Sign-Extension Suppressed
|
||||
|
||||
// SUBTRACT INSTRUCTIONS
|
||||
|
||||
{ "sub", CF_CHG1 }, // Sub From Accumulator
|
||||
{ "sub", CF_USE1|CF_CHG2 }, // Sub From Accumulator
|
||||
{ "sub", CF_USE1|CF_USE2|CF_CHG3 }, // Sub From Accumulator
|
||||
{ "subb", CF_USE1|CF_CHG2 }, // Sub From Accumulator With Borrow
|
||||
{ "subc", CF_USE1|CF_CHG2 }, // Subtract Conditionally
|
||||
{ "subs", CF_USE1|CF_CHG2 }, // Subtract From Accumulator With Sign Extension Suppressed
|
||||
|
||||
// MULTIPLY INSTRUCTIONS
|
||||
|
||||
{ "mpy", CF_USE1|CF_CHG2 }, // Multiply Without Rounding
|
||||
{ "mpy", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Without Rounding
|
||||
{ "mpyr", CF_USE1|CF_CHG2 }, // Multiply With Rounding
|
||||
{ "mpya", CF_CHG1 }, // Multiply by Accumulator A
|
||||
{ "mpyu", CF_USE1|CF_CHG2 }, // Multiply Unsigned
|
||||
{ "squr", CF_USE1|CF_CHG2 }, // Square
|
||||
|
||||
// MULTIPLY-ACCUMULATE AND MULTIPLY-SUBTRACT INSTRUCTIONS
|
||||
|
||||
{ "mac", CF_USE1|CF_CHG2 }, // Multiply Accumulate Without Rounding
|
||||
{ "mac", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Accumulate Without Rounding
|
||||
{ "macr", CF_USE1|CF_CHG2 }, // Multiply Accumulate With Rounding
|
||||
{ "macr", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Accumulate With Rounding
|
||||
{ "maca", CF_CHG1 }, // Multiply by Accumulator A and Accumulate Without Rounding
|
||||
{ "maca", CF_USE1|CF_CHG2 }, // Multiply by Accumulator A and Accumulate Without Rounding
|
||||
{ "maca", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply by Accumulator A and Accumulate Without Rounding
|
||||
{ "macar", CF_CHG1 }, // Multiply by Accumulator A and Accumulate With Rounding
|
||||
{ "macar", CF_USE1|CF_CHG2 }, // Multiply by Accumulator A and Accumulate With Rounding
|
||||
{ "macar", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply by Accumulator A and Accumulate With Rounding
|
||||
{ "macd", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply by Program Memory and Accumulate With Delay
|
||||
{ "macp", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply by Program Memory and Accumulate
|
||||
{ "macsu", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Signed by Unsigned and Accumulate
|
||||
{ "mas", CF_USE1|CF_CHG2 }, // Multiply and Subtract Without Rounding
|
||||
{ "mas", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply and Subtract Without Rounding
|
||||
{ "masr", CF_USE1|CF_CHG2 }, // Multiply and Subtract With Rounding
|
||||
{ "masr", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply and Subtract With Rounding
|
||||
// TMS320C54_mas,
|
||||
{ "masa", CF_CHG1 }, // Multiply by Accumulator A and Subtract Without Rounding
|
||||
{ "masa", CF_USE1|CF_CHG2 }, // Multiply by Accumulator A and Subtract Without Rounding
|
||||
{ "masa", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply by Accumulator A and Subtract Without Rounding
|
||||
{ "masar", CF_CHG1 }, // Multiply by Accumulator A and Subtract With Rounding
|
||||
{ "masar", CF_USE1|CF_CHG2 }, // Multiply by Accumulator A and Subtract With Rounding
|
||||
{ "masar", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply by Accumulator A and Subtract With Rounding
|
||||
{ "squra", CF_USE1|CF_CHG2 }, // Square and Accumulate
|
||||
{ "squrs", CF_USE1|CF_CHG2 }, // Square and Subtract
|
||||
|
||||
// DOUBLE INSTRUCTIONS
|
||||
|
||||
{ "dadd", CF_USE1|CF_CHG2 }, // Double-Precision/Dual 16-Bit Add to Accumulator
|
||||
{ "dadd", CF_USE1|CF_USE2|CF_CHG3 }, // Double-Precision/Dual 16-Bit Add to Accumulator
|
||||
{ "dadst", CF_USE1|CF_CHG2 }, // Double-Precision Load With T Add/Dual 16-Bit Load With T Add/Subtract
|
||||
{ "drsub", CF_USE1|CF_CHG2 }, // Double-Precision/Dual 16-Bit Subtract From Long Word
|
||||
{ "dsadt", CF_USE1|CF_CHG2 }, // Long-Word Load With T Add/Dual 16-Bit Load With T Subtract/Add
|
||||
{ "dsub", CF_USE1|CF_CHG2 }, // Double-Precision/Dual 16-Bit Subtract From Accumulator
|
||||
{ "dsubt", CF_USE1|CF_CHG2 }, // Long-Word Load With T Subtract/Dual 16-Bit Load With T Subtract
|
||||
|
||||
// APPLICATION-SPECIFIC INSTRUCTIONS
|
||||
|
||||
{ "abdst", CF_USE1|CF_USE2 }, // Absolute distance
|
||||
{ "abs", CF_CHG1 }, // Absolute Value of Accumulator
|
||||
{ "abs", CF_USE1|CF_CHG2 }, // Absolute Value of Accumulator
|
||||
{ "cmpl", CF_CHG1 }, // Complement Accumulator
|
||||
{ "cmpl", CF_USE1|CF_CHG2 }, // Complement Accumulator
|
||||
{ "delay", CF_USE1 }, // Memory Delay
|
||||
{ "exp", CF_USE1 }, // Accumulator Exponent
|
||||
{ "firs", CF_USE1|CF_USE2 }, // Symmetrical Finite Impulse Response Filter
|
||||
{ "lms", CF_USE1|CF_USE2 }, // Least Mean Square
|
||||
{ "max", CF_CHG1 }, // Accumulator Maximum
|
||||
{ "min", CF_CHG1 }, // Accumulator Minimum
|
||||
{ "neg", CF_CHG1 }, // Negate Accumulator
|
||||
{ "neg", CF_USE1|CF_CHG2 }, // Negate Accumulator
|
||||
{ "norm", CF_CHG1 }, // Normalization
|
||||
{ "norm", CF_USE1|CF_CHG2 }, // Normalization
|
||||
{ "poly", CF_USE1 }, // Polynominal Evaluation
|
||||
{ "rnd", CF_CHG1 }, // Round Accumulator
|
||||
{ "rnd", CF_USE1|CF_CHG2 }, // Round Accumulator
|
||||
{ "sat", CF_CHG1 }, // Saturate Accumulator
|
||||
{ "sqdst", CF_USE1|CF_USE2 }, // Square Distance
|
||||
|
||||
// LOGICAL OPERATIONS
|
||||
|
||||
// AND INSTRUCTIONS
|
||||
{ "and", CF_CHG1 }, // AND With Accumulator
|
||||
{ "and", CF_USE1|CF_CHG2 }, // AND With Accumulator
|
||||
{ "and", CF_USE1|CF_USE2|CF_CHG3 }, // AND With Accumulator
|
||||
{ "andm", CF_USE1|CF_CHG2 }, // AND Memory With Long Immediate
|
||||
|
||||
// OR INSTRUCTIONS
|
||||
|
||||
{ "or", CF_CHG1 }, // OR With Accumulator
|
||||
{ "or", CF_USE1|CF_CHG2 }, // OR With Accumulator
|
||||
{ "or", CF_USE1|CF_USE2|CF_CHG3 }, // OR With Accumulator
|
||||
{ "orm", CF_USE1|CF_CHG2 }, // OR Memory With Constant
|
||||
|
||||
// XOR INSTRUCTIONS
|
||||
|
||||
{ "xor", CF_CHG1 }, // Exclusive OR With Accumulator
|
||||
{ "xor", CF_USE1|CF_CHG2 }, // Exclusive OR With Accumulator
|
||||
{ "xor", CF_USE1|CF_USE2|CF_CHG3 }, // Exclusive OR With Accumulator
|
||||
{ "xorm", CF_USE1|CF_CHG2 }, // Exclusive OR Memory With Constant
|
||||
|
||||
// SHIFT INSTRUCTIONS
|
||||
|
||||
{ "rol", CF_CHG1 }, // Rotate Accumulator
|
||||
{ "roltc", CF_CHG1 }, // Rotate Accumulator Left Using TC
|
||||
{ "ror", CF_CHG1 }, // Rotate Accumulator Right
|
||||
{ "sfta", CF_CHG1|CF_USE2 }, // Shift Accumulator Arithmetically
|
||||
{ "sfta", CF_USE1|CF_USE2|CF_CHG3 }, // Shift Accumulator Arithmetically
|
||||
{ "sftc", CF_CHG1 }, // Shift Accumulator Conditionally
|
||||
{ "sftl", CF_CHG1|CF_USE2 }, // Shift Accumulator Logically
|
||||
{ "sftl", CF_USE1|CF_USE2|CF_CHG3 }, // Shift Accumulator Logically
|
||||
|
||||
// TEST INSTRUCTIONS
|
||||
|
||||
{ "bit", CF_USE1|CF_USE2 }, // Test Bit
|
||||
{ "bitf", CF_USE1|CF_USE2 }, // Test Bit Field Specified by Immediate Value
|
||||
{ "bitt", CF_USE1 }, // Test Bit Specified by T
|
||||
{ "cmpm", CF_USE1|CF_USE2 }, // Compare Memory With Long Immediate
|
||||
{ "cmpr", CF_USE1|CF_USE2 }, // Compare Auxiliary Register with AR0
|
||||
|
||||
// PROGRAM CONTROL OPERATIONS
|
||||
|
||||
// BRANCH INSTRUCTIONS
|
||||
|
||||
{ "b", CF_USE1|CF_STOP }, // Branch Unconditionally
|
||||
{ "bd", CF_USE1 }, // Branch Unconditionally
|
||||
{ "bacc", CF_USE1|CF_STOP }, // Branch to Location Specified by Accumulator
|
||||
{ "baccd", CF_USE1 }, // Branch to Location Specified by Accumulator
|
||||
{ "banz", CF_USE1|CF_USE2 }, // Branch on Auxiliary Register Not Zero
|
||||
{ "banzd", CF_USE1|CF_USE2 }, // Branch on Auxiliary Register Not Zero
|
||||
{ "bc", CF_USE1|CF_USE2 }, // Branch Conditionally
|
||||
{ "bc", CF_USE1|CF_USE2|CF_USE3 }, // Branch Conditionally
|
||||
{ "bcd", CF_USE1|CF_USE2 }, // Branch Conditionally
|
||||
{ "bcd", CF_USE1|CF_USE2|CF_USE3 }, // Branch Conditionally
|
||||
{ "fb", CF_USE1|CF_STOP }, // Far Branch Unconditionally
|
||||
{ "fbd", CF_USE1 }, // Far Branch Unconditionally
|
||||
{ "fbacc", CF_USE1 }, // Far Branch to Location Specified by Accumulator
|
||||
{ "fbaccd", CF_USE1 }, // Far Branch to Location Specified by Accumulator
|
||||
|
||||
// CALL INSTRUCTIONS
|
||||
|
||||
{ "cala", CF_USE1|CF_CALL }, // Call Subroutine at Location Specified by Accumulator
|
||||
{ "calad", CF_USE1|CF_CALL }, // Call Subroutine at Location Specified by Accumulator
|
||||
{ "call", CF_USE1|CF_CALL }, // Call Unconditionally
|
||||
{ "calld", CF_USE1|CF_CALL }, // Call Unconditionally
|
||||
{ "cc", CF_USE1|CF_USE2|CF_CALL }, // Call Conditionally
|
||||
{ "cc", CF_USE1|CF_USE2|CF_USE3|CF_CALL }, // Call Conditionally
|
||||
{ "ccd", CF_USE1|CF_USE2|CF_CALL }, // Call Conditionally
|
||||
{ "ccd", CF_USE1|CF_USE2|CF_USE3|CF_CALL }, // Call Conditionally
|
||||
{ "fcala", CF_USE1|CF_CALL }, // Far Call Subroutine at Location Specified by Accumulator
|
||||
{ "fcalad", CF_USE1|CF_CALL }, // Far Call Subroutine at Location Specified by Accumulator
|
||||
{ "fcall", CF_USE1|CF_CALL }, // Far Call Unconditionally
|
||||
{ "fcalld", CF_USE1|CF_CALL }, // Far Call Unconditionally
|
||||
|
||||
// INTERRUPT INSTRUCTIONS
|
||||
|
||||
{ "intr", CF_USE1|CF_CALL }, // Software Interrupt
|
||||
{ "trap", CF_USE1|CF_CALL }, // Software Interrupt
|
||||
|
||||
// RETURN INSTRUCTIONS
|
||||
|
||||
{ "fret", CF_STOP }, // Far Return
|
||||
{ "fretd", 0 }, // Far Return
|
||||
{ "frete", CF_STOP }, // Enable Interrupts and Far Return From Interrupt
|
||||
{ "freted", 0 }, // Enable Interrupts and Far Return From Interrupt
|
||||
{ "rc", CF_USE1 }, // Return Conditionally
|
||||
{ "rc", CF_USE1|CF_USE2 }, // Return Conditionally
|
||||
{ "rc", CF_USE1|CF_USE2|CF_USE3 }, // Return Conditionally
|
||||
{ "rcd", CF_USE1 }, // Return Conditionally
|
||||
{ "rcd", CF_USE1|CF_USE2 }, // Return Conditionally
|
||||
{ "rcd", CF_USE1|CF_USE2|CF_USE3 }, // Return Conditionally
|
||||
{ "ret", CF_STOP }, // Return
|
||||
{ "retd", 0 }, // Return
|
||||
{ "rete", CF_STOP }, // Enable Interrupts and Far Return From Interrupt
|
||||
{ "reted", 0 }, // Enable Interrupts and Far Return From Interrupt
|
||||
{ "retf", CF_STOP }, // Enable Interrupts and Fast Return From Interrupt
|
||||
{ "retfd", 0 }, // Enable Interrupts and Fast Return From Interrupt
|
||||
|
||||
// REPEAT INSTRUCTIONS
|
||||
|
||||
{ "rpt", CF_USE1 }, // Repeat Next Instruction
|
||||
{ "rptb", CF_USE1 }, // Block Repeat
|
||||
{ "rptbd", CF_USE1 }, // Block Repeat
|
||||
{ "rptz", CF_CHG1|CF_USE2 }, // Repeat Next Instruction And Clear Accumulator
|
||||
|
||||
// STACK MANIPULATING INSTRUCTIONS
|
||||
|
||||
{ "frame", CF_USE1 }, // Stack Pointer Immediate Offset
|
||||
{ "popd", CF_CHG1 }, // Pop Top of Stack to Data Memory
|
||||
{ "popm", CF_CHG1 }, // Pop Top of Stack to Memory-Mapped Register
|
||||
{ "pshd", CF_USE1 }, // Push Data-Memory Value Onto Stack
|
||||
{ "pshm", CF_USE1 }, // Push Memory-Mapped Register Onto Stack
|
||||
|
||||
// MISCELLANEOUS PROGRAM-CONTROL INSTRUCTIONS
|
||||
|
||||
{ "idle", CF_USE1 }, // Idle Until Interrupt
|
||||
{ "mar", CF_USE1 }, // Modify Auxiliary Register
|
||||
{ "nop", 0 }, // No Operation
|
||||
{ "reset", 0 }, // Software Reset
|
||||
{ "rsbx", CF_CHG1 }, // Reset Status Register Bit
|
||||
{ "rsbx", CF_USE1|CF_USE2 }, // Reset Status Register Bit
|
||||
{ "ssbx", CF_CHG1 }, // Set Status Register Bit
|
||||
{ "ssbx", CF_USE1|CF_USE2 }, // Set Status Register Bit
|
||||
{ "xc", CF_USE1|CF_USE2 }, // Execute Conditionally
|
||||
{ "xc", CF_USE1|CF_USE2|CF_USE3 }, // Execute Conditionally
|
||||
|
||||
// LOAD AND STORE OPERATIONS
|
||||
|
||||
// LOAD INSTRUCTIONS
|
||||
|
||||
{ "dld", CF_USE1|CF_CHG2 }, // Double-Precision/Dual 16-Bit Long-Word Load to Accumulator
|
||||
{ "ld", CF_CHG1 }, // Load Accumulator With Shift
|
||||
{ "ld", CF_USE1|CF_CHG2 }, // Load Accumulator With Shift
|
||||
{ "ld", CF_USE1|CF_USE2|CF_CHG3 }, // Load Accumulator With Shift
|
||||
{ "ldm", CF_USE1|CF_CHG2 }, // Load Memory-Mapped Register
|
||||
{ "ldr", CF_USE1|CF_CHG2 }, // Load Memory Value in Accumulator High With Rounding
|
||||
{ "ldu", CF_USE1|CF_CHG2 }, // Load Unsigned Memory Value
|
||||
{ "ltd", CF_USE1 }, // Load T and insert Delay
|
||||
|
||||
// STORE INSTRUCTIONS
|
||||
|
||||
{ "dst", CF_USE1|CF_CHG2 }, // Store Accumulator in Long Word
|
||||
{ "st", CF_USE1|CF_CHG2 }, // Store T, TRN, or Immediate Value into Memory
|
||||
{ "sth", CF_USE1|CF_CHG2 }, // Store Accumulator High Into Memory
|
||||
{ "sth", CF_USE1|CF_USE2|CF_CHG3 }, // Store Accumulator High Into Memory
|
||||
{ "stl", CF_USE1|CF_CHG2 }, // Store Accumulator Low Into Memory
|
||||
{ "stl", CF_USE1|CF_USE2|CF_CHG3 }, // Store Accumulator Low Into Memory
|
||||
{ "stlm", CF_USE1|CF_CHG2 }, // Store Accumulator Low Into Memory-Mapped Register
|
||||
{ "stm", CF_USE1|CF_CHG2 }, // Store Immediate Value Into Memory-Mapped Register
|
||||
|
||||
// CONDITIONAL STORE INSTRUCTIONS
|
||||
|
||||
{ "cmps", CF_USE1|CF_CHG2 }, // Compare, Select and Store Maximum
|
||||
{ "saccd", CF_USE1|CF_CHG2|CF_USE3 }, // Store Accumulator Conditionally
|
||||
{ "srccd", CF_CHG1|CF_USE2 }, // Store Block Repeat Counter Conditionally
|
||||
{ "strcd", CF_CHG1|CF_USE2 }, // Store T Conditionally
|
||||
|
||||
// PARALLEL LOAD AND STORE INSTRUCTIONS
|
||||
|
||||
{ "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Load // TMS320C54_st_ld
|
||||
|
||||
// PARALLEL LOAD AND MULTIPLY INSTRUCTIONS
|
||||
|
||||
{ "ld", CF_USE1|CF_CHG2|CF_CHG3 }, // Load Accumulator With Parallel Multiply Accumulate Without Rounding // TMS320C54_ld_mac
|
||||
{ "ld", CF_USE1|CF_CHG2|CF_CHG3 }, // Load Accumulator With Parallel Multiply Accumulate With Rounding // TMS320C54_ld_macr
|
||||
{ "ld", CF_USE1|CF_CHG2|CF_CHG3 }, // Load Accumulator With Parallel Multiply Subtract Without Rounding // TMS320C54_ld_mas
|
||||
{ "ld", CF_USE1|CF_CHG2|CF_CHG3 }, // Load Accumulator With Parallel Multiply Subtract With Rounding // TMS320C54_ld_masr
|
||||
|
||||
// PARALLEL STORE AND ADD/SUBSTRACT INSTRUCTIONS
|
||||
|
||||
{ "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Add // TMS320C54_st_add
|
||||
{ "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Subtract // TMS320C54_st_sub
|
||||
|
||||
// PARALLEL STORE AND MULTIPLY INSTRUCTIONS
|
||||
|
||||
{ "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Multiply Accumulate Without Rounding // TMS320C54_st_mac
|
||||
{ "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Multiply Accumulate With Rounding // TMS320C54_st_macr
|
||||
{ "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Multiply Subtract Without Rounding // TMS320C54_st_mas
|
||||
{ "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Multiply Subtract With Rounding // TMS320C54_st_masr
|
||||
{ "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Multiply // TMS320C54_st_mpy
|
||||
|
||||
// MISCELLANEOUS LOAD-TYPE AND STORE-TYPE INSTRUCTIONS
|
||||
|
||||
{ "mvdd", CF_USE1|CF_CHG2 }, // Move Data From Data Memory to Data Memory With X,Y Addressing
|
||||
{ "mvdk", CF_USE1|CF_CHG2 }, // Move Data From Data Memory to Data Memory With Destination Addressing
|
||||
{ "mvdm", CF_USE1|CF_CHG2 }, // Move Data From Data Memory to Memory-Mapped Register
|
||||
{ "mvdp", CF_USE1|CF_CHG2 }, // Move Data From Data Memory to Program Memory
|
||||
{ "mvkd", CF_USE1|CF_CHG2 }, // Move Data From Data Memory to Data Memory With Source Addressing
|
||||
{ "mvmd", CF_USE1|CF_CHG2 }, // Move Data From Memory-Mapped Register to Data Memory
|
||||
{ "mvmm", CF_USE1|CF_CHG2 }, // Move Data From Memory-Mapped Register to Memory-Mapped Register
|
||||
{ "mvpd", CF_USE1|CF_CHG2 }, // Move Data From Program Memory to Data Memory
|
||||
{ "portr", CF_USE1|CF_USE2 }, // Read Data From Port
|
||||
{ "portw", CF_USE1|CF_USE2 }, // Write Data to Port
|
||||
{ "reada", CF_CHG1 }, // Read Program Memory Addressed by Accumulator A and Store in Data Memory
|
||||
{ "writa", CF_USE1 }, // Write Data to Program Memory Addressed by Accumulator A
|
||||
|
||||
};
|
||||
|
||||
CASSERT(qnumber(Instructions) == TMS320C54_last);
|
||||
311
idasdk76/module/tms320c54/ins.hpp
Normal file
311
idasdk76/module/tms320c54/ins.hpp
Normal file
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2021 Hex-Rays
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __INSTRS_HPP
|
||||
#define __INSTRS_HPP
|
||||
|
||||
extern const instruc_t Instructions[];
|
||||
|
||||
enum nameNum ENUM_SIZE(uint16)
|
||||
{
|
||||
|
||||
TMS320C54_null = 0, // Unknown Operation
|
||||
|
||||
// ARITHMETIC OPERATIONS
|
||||
|
||||
// ADD INSTRUCTIONS
|
||||
|
||||
TMS320C54_add1, // Add to Accumulator
|
||||
TMS320C54_add2, // Add to Accumulator
|
||||
TMS320C54_add3, // Add to Accumulator
|
||||
TMS320C54_addc, // Add to Accumulator With Carry
|
||||
TMS320C54_addm, // Add Long-Immediate Value to Memory
|
||||
TMS320C54_adds, // Add to Accumulator With Sign-Extension Suppressed
|
||||
|
||||
// SUBTRACT INSTRUCTIONS
|
||||
|
||||
TMS320C54_sub1, // Sub From Accumulator
|
||||
TMS320C54_sub2, // Sub From Accumulator
|
||||
TMS320C54_sub3, // Sub From Accumulator
|
||||
TMS320C54_subb, // Sub From Accumulator With Borrow
|
||||
TMS320C54_subc, // Subtract Conditionally
|
||||
TMS320C54_subs, // Subtract From Accumulator With Sign Extension Suppressed
|
||||
|
||||
// MULTIPLY INSTRUCTIONS
|
||||
|
||||
TMS320C54_mpy2, // Multiply Without Rounding
|
||||
TMS320C54_mpy3, // Multiply Without Rounding
|
||||
TMS320C54_mpyr2, // Multiply With Rounding
|
||||
TMS320C54_mpya, // Multiply by Accumulator A
|
||||
TMS320C54_mpyu, // Multiply Unsigned
|
||||
TMS320C54_squr, // Square
|
||||
|
||||
// MULTIPLY-ACCUMULATE AND MULTIPLY-SUBTRACT INSTRUCTIONS
|
||||
|
||||
TMS320C54_mac2, // Multiply Accumulate Without Rounding
|
||||
TMS320C54_mac3, // Multiply Accumulate Without Rounding
|
||||
TMS320C54_macr2, // Multiply Accumulate With Rounding
|
||||
TMS320C54_macr3, // Multiply Accumulate With Rounding
|
||||
TMS320C54_maca1, // Multiply by Accumulator A and Accumulate Without Rounding
|
||||
TMS320C54_maca2, // Multiply by Accumulator A and Accumulate Without Rounding
|
||||
TMS320C54_maca3, // Multiply by Accumulator A and Accumulate Without Rounding
|
||||
TMS320C54_macar1, // Multiply by Accumulator A and Accumulate With Rounding
|
||||
TMS320C54_macar2, // Multiply by Accumulator A and Accumulate With Rounding
|
||||
TMS320C54_macar3, // Multiply by Accumulator A and Accumulate With Rounding
|
||||
TMS320C54_macd, // Multiply by Program Memory and Accumulate With Delay
|
||||
TMS320C54_macp, // Multiply by Program Memory and Accumulate
|
||||
TMS320C54_macsu, // Multiply Signed by Unsigned and Accumulate
|
||||
TMS320C54_mas2, // Multiply and Subtract Without Rounding
|
||||
TMS320C54_mas3, // Multiply and Subtract Without Rounding
|
||||
TMS320C54_masr2, // Multiply and Subtract With Rounding
|
||||
TMS320C54_masr3, // Multiply and Subtract With Rounding
|
||||
// TMS320C54_mas,
|
||||
TMS320C54_masa1, // Multiply by Accumulator A and Subtract Without Rounding
|
||||
TMS320C54_masa2, // Multiply by Accumulator A and Subtract Without Rounding
|
||||
TMS320C54_masa3, // Multiply by Accumulator A and Subtract Without Rounding
|
||||
TMS320C54_masar1, // Multiply by Accumulator A and Subtract With Rounding
|
||||
TMS320C54_masar2, // Multiply by Accumulator A and Subtract With Rounding
|
||||
TMS320C54_masar3, // Multiply by Accumulator A and Subtract With Rounding
|
||||
TMS320C54_squra, // Square and Accumulate
|
||||
TMS320C54_squrs, // Square and Subtract
|
||||
|
||||
// DOUBLE INSTRUCTIONS
|
||||
|
||||
TMS320C54_dadd2, // Double-Precision/Dual 16-Bit Add to Accumulator
|
||||
TMS320C54_dadd3, // Double-Precision/Dual 16-Bit Add to Accumulator
|
||||
TMS320C54_dadst, // Double-Precision Load With T Add/Dual 16-Bit Load With T Add/Subtract
|
||||
TMS320C54_drsub, // Double-Precision/Dual 16-Bit Subtract From Long Word
|
||||
TMS320C54_dsadt, // Long-Word Load With T Add/Dual 16-Bit Load With T Subtract/Add
|
||||
TMS320C54_dsub, // Double-Precision/Dual 16-Bit Subtract From Accumulator
|
||||
TMS320C54_dsubt, // Long-Word Load With T Subtract/Dual 16-Bit Load With T Subtract
|
||||
|
||||
// APPLICATION-SPECIFIC INSTRUCTIONS
|
||||
|
||||
TMS320C54_abdst, // Absolute distance
|
||||
TMS320C54_abs1, // Absolute Value of Accumulator
|
||||
TMS320C54_abs2, // Absolute Value of Accumulator
|
||||
TMS320C54_cmpl1, // Complement Accumulator
|
||||
TMS320C54_cmpl2, // Complement Accumulator
|
||||
TMS320C54_delay, // Memory Delay
|
||||
TMS320C54_exp, // Accumulator Exponent
|
||||
TMS320C54_firs, // Symmetrical Finite Impulse Response Filter
|
||||
TMS320C54_lms, // Least Mean Square
|
||||
TMS320C54_max, // Accumulator Maximum
|
||||
TMS320C54_min, // Accumulator Minimum
|
||||
TMS320C54_neg1, // Negate Accumulator
|
||||
TMS320C54_neg2, // Negate Accumulator
|
||||
TMS320C54_norm1, // Normalization
|
||||
TMS320C54_norm2, // Normalization
|
||||
TMS320C54_poly, // Polynominal Evaluation
|
||||
TMS320C54_rnd1, // Round Accumulator
|
||||
TMS320C54_rnd2, // Round Accumulator
|
||||
TMS320C54_sat, // Saturate Accumulator
|
||||
TMS320C54_sqdst, // Square Distance
|
||||
|
||||
// LOGICAL OPERATIONS
|
||||
|
||||
// AND INSTRUCTIONS
|
||||
|
||||
TMS320C54_and1, // AND With Accumulator
|
||||
TMS320C54_and2, // AND With Accumulator
|
||||
TMS320C54_and3, // AND With Accumulator
|
||||
TMS320C54_andm, // AND Memory With Long Immediate
|
||||
|
||||
// OR INSTRUCTIONS
|
||||
|
||||
TMS320C54_or1, // OR With Accumulator
|
||||
TMS320C54_or2, // OR With Accumulator
|
||||
TMS320C54_or3, // OR With Accumulator
|
||||
TMS320C54_orm, // OR Memory With Constant
|
||||
|
||||
// XOR INSTRUCTIONS
|
||||
|
||||
TMS320C54_xor1, // Exclusive OR With Accumulator
|
||||
TMS320C54_xor2, // Exclusive OR With Accumulator
|
||||
TMS320C54_xor3, // Exclusive OR With Accumulator
|
||||
TMS320C54_xorm, // Exclusive OR Memory With Constant
|
||||
|
||||
// SHIFT INSTRUCTIONS
|
||||
|
||||
TMS320C54_rol, // Rotate Accumulator
|
||||
TMS320C54_roltc, // Rotate Accumulator Left Using TC
|
||||
TMS320C54_ror, // Rotate Accumulator Right
|
||||
TMS320C54_sfta2, // Shift Accumulator Arithmetically
|
||||
TMS320C54_sfta3, // Shift Accumulator Arithmetically
|
||||
TMS320C54_sftc, // Shift Accumulator Conditionally
|
||||
TMS320C54_sftl2, // Shift Accumulator Logically
|
||||
TMS320C54_sftl3, // Shift Accumulator Logically
|
||||
|
||||
// TEST INSTRUCTIONS
|
||||
|
||||
TMS320C54_bit, // Test Bit
|
||||
TMS320C54_bitf, // Test Bit Field Specified by Immediate Value
|
||||
TMS320C54_bitt, // Test Bit Specified by T
|
||||
TMS320C54_cmpm, // Compare Memory With Long Immediate
|
||||
TMS320C54_cmpr, // Compare Auxiliary Register with AR0
|
||||
|
||||
// PROGRAM CONTROL OPERATIONS
|
||||
|
||||
// BRANCH INSTRUCTIONS
|
||||
|
||||
TMS320C54_b, // Branch Unconditionally
|
||||
TMS320C54_bd, // Branch Unconditionally
|
||||
TMS320C54_bacc, // Branch to Location Specified by Accumulator
|
||||
TMS320C54_baccd, // Branch to Location Specified by Accumulator
|
||||
TMS320C54_banz, // Branch on Auxiliary Register Not Zero
|
||||
TMS320C54_banzd, // Branch on Auxiliary Register Not Zero
|
||||
TMS320C54_bc2, // Branch Conditionally
|
||||
TMS320C54_bc3, // Branch Conditionally
|
||||
TMS320C54_bcd2, // Branch Conditionally
|
||||
TMS320C54_bcd3, // Branch Conditionally
|
||||
TMS320C54_fb, // Far Branch Unconditionally
|
||||
TMS320C54_fbd, // Far Branch Unconditionally
|
||||
TMS320C54_fbacc, // Far Branch to Location Specified by Accumulator
|
||||
TMS320C54_fbaccd, // Far Branch to Location Specified by Accumulator
|
||||
|
||||
// CALL INSTRUCTIONS
|
||||
|
||||
TMS320C54_cala, // Call Subroutine at Location Specified by Accumulator
|
||||
TMS320C54_calad, // Call Subroutine at Location Specified by Accumulator
|
||||
TMS320C54_call, // Call Unconditionally
|
||||
TMS320C54_calld, // Call Unconditionally
|
||||
TMS320C54_cc2, // Call Conditionally
|
||||
TMS320C54_cc3, // Call Conditionally
|
||||
TMS320C54_ccd2, // Call Conditionally
|
||||
TMS320C54_ccd3, // Call Conditionally
|
||||
TMS320C54_fcala, // Far Call Subroutine at Location Specified by Accumulator
|
||||
TMS320C54_fcalad, // Far Call Subroutine at Location Specified by Accumulator
|
||||
TMS320C54_fcall, // Far Call Unconditionally
|
||||
TMS320C54_fcalld, // Far Call Unconditionally
|
||||
|
||||
// INTERRUPT INSTRUCTIONS
|
||||
|
||||
TMS320C54_intr, // Software Interrupt
|
||||
TMS320C54_trap, // Software Interrupt
|
||||
|
||||
// RETURN INSTRUCTIONS
|
||||
|
||||
TMS320C54_fret, // Far Return
|
||||
TMS320C54_fretd, // Far Return
|
||||
TMS320C54_frete, // Enable Interrupts and Far Return From Interrupt
|
||||
TMS320C54_freted, // Enable Interrupts and Far Return From Interrupt
|
||||
TMS320C54_rc1, // Return Conditionally
|
||||
TMS320C54_rc2, // Return Conditionally
|
||||
TMS320C54_rc3, // Return Conditionally
|
||||
TMS320C54_rcd1, // Return Conditionally
|
||||
TMS320C54_rcd2, // Return Conditionally
|
||||
TMS320C54_rcd3, // Return Conditionally
|
||||
TMS320C54_ret, // Return
|
||||
TMS320C54_retd, // Return
|
||||
TMS320C54_rete, // Enable Interrupts and Return From Interrupt
|
||||
TMS320C54_reted, // Enable Interrupts and Return From Interrupt
|
||||
TMS320C54_retf, // Enable Interrupts and Fast Return From Interrupt
|
||||
TMS320C54_retfd, // Enable Interrupts and Fast Return From Interrupt
|
||||
|
||||
// REPEAT INSTRUCTIONS
|
||||
|
||||
TMS320C54_rpt, // Repeat Next Instruction
|
||||
TMS320C54_rptb, // Block Repeat
|
||||
TMS320C54_rptbd, // Block Repeat
|
||||
TMS320C54_rptz, // Repeat Next Instruction And Clear Accumulator
|
||||
|
||||
// STACK MANIPULATING INSTRUCTIONS
|
||||
|
||||
TMS320C54_frame, // Stack Pointer Immediate Offset
|
||||
TMS320C54_popd, // Pop Top of Stack to Data Memory
|
||||
TMS320C54_popm, // Pop Top of Stack to Memory-Mapped Register
|
||||
TMS320C54_pshd, // Push Data-Memory Value Onto Stack
|
||||
TMS320C54_pshm, // Push Memory-Mapped Register Onto Stack
|
||||
|
||||
// MISCELLANEOUS PROGRAM-CONTROL INSTRUCTIONS
|
||||
|
||||
TMS320C54_idle, // Idle Until Interrupt
|
||||
TMS320C54_mar, // Modify Auxiliary Register
|
||||
TMS320C54_nop, // No Operation
|
||||
TMS320C54_reset, // Software Reset
|
||||
TMS320C54_rsbx1, // Reset Status Register Bit
|
||||
TMS320C54_rsbx2, // Reset Status Register Bit
|
||||
TMS320C54_ssbx1, // Set Status Register Bit
|
||||
TMS320C54_ssbx2, // Set Status Register Bit
|
||||
TMS320C54_xc2, // Execute Conditionally
|
||||
TMS320C54_xc3, // Execute Conditionally
|
||||
|
||||
// LOAD AND STORE OPERATIONS
|
||||
|
||||
// LOAD INSTRUCTIONS
|
||||
|
||||
TMS320C54_dld, // Double-Precision/Dual 16-Bit Long-Word Load to Accumulator
|
||||
TMS320C54_ld1, // Load Accumulator With Shift
|
||||
TMS320C54_ld2, // Load Accumulator With Shift
|
||||
TMS320C54_ld3, // Load Accumulator With Shift
|
||||
TMS320C54_ldm, // Load Memory-Mapped Register
|
||||
TMS320C54_ldr, // Load Memory Value in Accumulator High With Rounding
|
||||
TMS320C54_ldu, // Load Unsigned Memory Value
|
||||
TMS320C54_ltd, // Load T and insert Delay
|
||||
|
||||
// STORE INSTRUCTIONS
|
||||
|
||||
TMS320C54_dst, // Store Accumulator in Long Word
|
||||
TMS320C54_st, // Store T, TRN, or Immediate Value into Memory
|
||||
TMS320C54_sth2, // Store Accumulator High Into Memory
|
||||
TMS320C54_sth3, // Store Accumulator High Into Memory
|
||||
TMS320C54_stl2, // Store Accumulator Low Into Memory
|
||||
TMS320C54_stl3, // Store Accumulator Low Into Memory
|
||||
TMS320C54_stlm, // Store Accumulator Low Into Memory-Mapped Register
|
||||
TMS320C54_stm, // Store Immediate Value Into Memory-Mapped Register
|
||||
|
||||
// CONDITIONAL STORE INSTRUCTIONS
|
||||
|
||||
TMS320C54_cmps, // Compare, Select and Store Maximum
|
||||
TMS320C54_saccd, // Store Accumulator Conditionally
|
||||
TMS320C54_srccd, // Store Block Repeat Counter Conditionally
|
||||
TMS320C54_strcd, // Store T Conditionally
|
||||
|
||||
// PARALLEL LOAD AND STORE INSTRUCTIONS
|
||||
|
||||
TMS320C54_st_ld, // Store Accumulator With Parallel Load
|
||||
|
||||
// PARALLEL LOAD AND MULTIPLY INSTRUCTIONS
|
||||
|
||||
TMS320C54_ld_mac, // Load Accumulator With Parallel Multiply Accumulate Without Rounding
|
||||
TMS320C54_ld_macr, // Load Accumulator With Parallel Multiply Accumulate With Rounding
|
||||
TMS320C54_ld_mas, // Load Accumulator With Parallel Multiply Subtract Without Rounding
|
||||
TMS320C54_ld_masr, // Load Accumulator With Parallel Multiply Subtract With Rounding
|
||||
|
||||
// PARALLEL STORE AND ADD/SUBSTRACT INSTRUCTIONS
|
||||
|
||||
TMS320C54_st_add, // Store Accumulator With Parallel Add
|
||||
TMS320C54_st_sub, // Store Accumulator With Parallel Subtract
|
||||
|
||||
// PARALLEL STORE AND MULTIPLY INSTRUCTIONS
|
||||
|
||||
TMS320C54_st_mac, // Store Accumulator With Parallel Multiply Accumulate Without Rounding
|
||||
TMS320C54_st_macr, // Store Accumulator With Parallel Multiply Accumulate With Rounding
|
||||
TMS320C54_st_mas, // Store Accumulator With Parallel Multiply Subtract Without Rounding
|
||||
TMS320C54_st_masr, // Store Accumulator With Parallel Multiply Subtract With Rounding
|
||||
TMS320C54_st_mpy, // Store Accumulator With Parallel Multiply
|
||||
|
||||
// MISCELLANEOUS LOAD-TYPE AND STORE-TYPE INSTRUCTIONS
|
||||
|
||||
TMS320C54_mvdd, // Move Data From Data Memory to Data Memory With X,Y Addressing
|
||||
TMS320C54_mvdk, // Move Data From Data Memory to Data Memory With Destination Addressing
|
||||
TMS320C54_mvdm, // Move Data From Data Memory to Memory-Mapped Register
|
||||
TMS320C54_mvdp, // Move Data From Data Memory to Program Memory
|
||||
TMS320C54_mvkd, // Move Data From Data Memory to Data Memory With Source Addressing
|
||||
TMS320C54_mvmd, // Move Data From Memory-Mapped Register to Data Memory
|
||||
TMS320C54_mvmm, // Move Data From Memory-Mapped Register to Memory-Mapped Register
|
||||
TMS320C54_mvpd, // Move Data From Program Memory to Data Memory
|
||||
TMS320C54_portr, // Read Data From Port
|
||||
TMS320C54_portw, // Write Data to Port
|
||||
TMS320C54_reada, // Read Program Memory Addressed by Accumulator A and Store in Data Memory
|
||||
TMS320C54_writa, // Write Data to Program Memory Addressed by Accumulator A
|
||||
|
||||
TMS320C54_last
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
60
idasdk76/module/tms320c54/makefile
Normal file
60
idasdk76/module/tms320c54/makefile
Normal file
@@ -0,0 +1,60 @@
|
||||
PROC=tms32054
|
||||
CONFIGS=tms320c54.cfg
|
||||
|
||||
|
||||
include ../module.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)OBJS$(O) :
|
||||
$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \
|
||||
$(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \
|
||||
$(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
|
||||
../iohandler.hpp ana.cpp ins.hpp tms320c54.hpp
|
||||
$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
|
||||
../iohandler.hpp emu.cpp ins.hpp tms320c54.hpp
|
||||
$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \
|
||||
$(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \
|
||||
$(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
|
||||
ins.cpp ins.hpp tms320c54.hpp
|
||||
$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)segregs.hpp $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp \
|
||||
../idaidp.hpp ../iohandler.hpp ins.hpp out.cpp \
|
||||
tms320c54.hpp
|
||||
$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \
|
||||
$(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \
|
||||
$(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
|
||||
../iohandler.hpp ins.hpp notify_codes.hpp reg.cpp \
|
||||
tms320c54.hpp
|
||||
33
idasdk76/module/tms320c54/notify_codes.hpp
Normal file
33
idasdk76/module/tms320c54/notify_codes.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2021 Hex-Rays
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TMS320C54_NOTIFY_CODES_HPP
|
||||
#define __TMS320C54_NOTIFY_CODES_HPP
|
||||
|
||||
#include <idp.hpp>
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// The following events are supported by the TMS320C54 module in the ph.notify() function
|
||||
namespace tms320c54_module_t
|
||||
{
|
||||
enum event_codes_t
|
||||
{
|
||||
ev_set_dataseg = processor_t::ev_loader + 2,
|
||||
};
|
||||
|
||||
inline processor_t::event_t idp_ev(event_codes_t ev)
|
||||
{
|
||||
return processor_t::event_t(ev);
|
||||
}
|
||||
|
||||
inline void set_dataseg(ea_t ea)
|
||||
{
|
||||
processor_t::notify(idp_ev(ev_set_dataseg), ea);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __TMS320C54_NOTIFY_CODES_HPP
|
||||
467
idasdk76/module/tms320c54/out.cpp
Normal file
467
idasdk76/module/tms320c54/out.cpp
Normal file
@@ -0,0 +1,467 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tms320c54.hpp"
|
||||
#include <frame.hpp>
|
||||
#include <segregs.hpp>
|
||||
#include <struct.hpp>
|
||||
|
||||
// simple wrapper class for syntactic sugar of member functions
|
||||
// this class may have only simple member functions.
|
||||
// virtual functions and data fields are forbidden, otherwise the class
|
||||
// layout may change
|
||||
class out_tms320c54_t : public outctx_t
|
||||
{
|
||||
out_tms320c54_t(void) = delete; // not used
|
||||
|
||||
tms320c54_t &pm() { return *static_cast<tms320c54_t *>(procmod); }
|
||||
public:
|
||||
bool out_operand(const op_t &x);
|
||||
void out_insn(void);
|
||||
void out_address(ea_t ea, const op_t &x, bool mapping, bool at);
|
||||
void out_cond8(char value);
|
||||
};
|
||||
CASSERT(sizeof(out_tms320c54_t) == sizeof(outctx_t));
|
||||
|
||||
DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_tms320c54_t)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_tms320c54_t::out_address(ea_t ea, const op_t &x, bool mapping, bool at)
|
||||
{
|
||||
regnum_t reg = pm().get_mapped_register(ea);
|
||||
if ( mapping && reg != rnone )
|
||||
{
|
||||
out_register(ph.reg_names[reg]);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef TMS320C54_NO_NAME_NO_REF
|
||||
qstring qbuf;
|
||||
// since tms320c54 uses memory mapping, we turn off verification
|
||||
// of name expression values (4th arg of get_name_expr is BADADDR)
|
||||
if ( get_name_expr(&qbuf, insn.ea+x.offb, x.n, ea, BADADDR) > 0 )
|
||||
{
|
||||
if ( at )
|
||||
out_symbol('@');
|
||||
out_line(qbuf.begin());
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
out_tagon(COLOR_ERROR);
|
||||
out_value(x, OOF_ADDR|OOFW_32);
|
||||
out_tagoff(COLOR_ERROR);
|
||||
remember_problem(PR_NONAME, insn.ea);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
const char *get_cond8(char value)
|
||||
{
|
||||
switch ( value )
|
||||
{
|
||||
case COND8_UNC: return "unc";
|
||||
case COND8_NBIO: return "nbio";
|
||||
case COND8_BIO: return "bio";
|
||||
case COND8_NC: return "nc";
|
||||
case COND8_C: return "c";
|
||||
case COND8_NTC: return "ntc";
|
||||
case COND8_TC: return "tc";
|
||||
case COND8_AGEQ: return "ageq";
|
||||
case COND8_ALT: return "alt";
|
||||
case COND8_ANEQ: return "aneq";
|
||||
case COND8_AEQ: return "aeq";
|
||||
case COND8_AGT: return "agt";
|
||||
case COND8_ALEQ: return "aleq";
|
||||
case COND8_ANOV: return "anov";
|
||||
case COND8_AOV: return "aov";
|
||||
case COND8_BGEQ: return "bgeq";
|
||||
case COND8_BLT: return "blt";
|
||||
case COND8_BNEQ: return "bneq";
|
||||
case COND8_BEQ: return "beq";
|
||||
case COND8_BGT: return "bgt";
|
||||
case COND8_BLEQ: return "bleq";
|
||||
case COND8_BNOV: return "bnov";
|
||||
case COND8_BOV: return "bov";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_tms320c54_t::out_cond8(char value)
|
||||
{
|
||||
const char *cond = get_cond8(value);
|
||||
QASSERT(256, cond != NULL);
|
||||
out_line(cond, COLOR_REG);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool out_tms320c54_t::out_operand(const op_t &x)
|
||||
{
|
||||
ea_t ea;
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_void:
|
||||
return 0;
|
||||
|
||||
case o_reg:
|
||||
out_register(ph.reg_names[x.reg]);
|
||||
break;
|
||||
|
||||
case o_near:
|
||||
case o_far:
|
||||
ea = calc_code_mem(insn, x.addr, x.type == o_near);
|
||||
out_address(ea, x, false, false);
|
||||
break;
|
||||
|
||||
case o_imm:
|
||||
{
|
||||
const char *name = NULL;
|
||||
if ( pm().idpflags & TMS320C54_IO && x.IOimm )
|
||||
name = pm().find_sym(x.value);
|
||||
if ( !x.NoCardinal )
|
||||
out_symbol('#');
|
||||
if ( name != NULL && name[0] != '\0' )
|
||||
{
|
||||
out_line(name, COLOR_IMPNAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !x.Signed )
|
||||
out_value(x, OOFW_IMM);
|
||||
else
|
||||
out_value(x, OOFS_IFSIGN|OOF_SIGNED|OOF_NUMBER|OOFW_IMM);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case o_local:
|
||||
out_value(x, OOF_ADDR|OOFW_32);
|
||||
break;
|
||||
|
||||
case o_mmr:
|
||||
case o_mem:
|
||||
case o_farmem:
|
||||
if ( x.IndirectAddressingMOD == ABSOLUTE_INDIRECT_ADRESSING )
|
||||
{
|
||||
out_symbol('*');
|
||||
out_symbol('(');
|
||||
}
|
||||
ea = pm().calc_data_mem(insn, x.addr, x.type == o_mem);
|
||||
if ( ea != BADADDR )
|
||||
{
|
||||
// no '@' if absolute "indirect" adressing
|
||||
bool at = x.IndirectAddressingMOD != ABSOLUTE_INDIRECT_ADRESSING;
|
||||
out_address(ea, x, true, at);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_value(x, OOF_ADDR|OOFW_32);
|
||||
}
|
||||
if ( x.IndirectAddressingMOD == ABSOLUTE_INDIRECT_ADRESSING )
|
||||
out_symbol(')');
|
||||
break;
|
||||
|
||||
case o_displ: // Indirect addressing mode
|
||||
{
|
||||
char buf[8];
|
||||
const char *reg = ph.reg_names[x.reg];
|
||||
switch ( x.IndirectAddressingMOD )
|
||||
{
|
||||
case 0:
|
||||
qsnprintf(buf, sizeof(buf), "*%s",reg);
|
||||
out_register(buf);
|
||||
break;
|
||||
case 1:
|
||||
qsnprintf(buf, sizeof(buf), "*%s-",reg);
|
||||
out_register(buf);
|
||||
break;
|
||||
case 2:
|
||||
qsnprintf(buf, sizeof(buf), "*%s+",reg);
|
||||
out_register(buf);
|
||||
break;
|
||||
case 3:
|
||||
qsnprintf(buf, sizeof(buf), "*+%s",reg);
|
||||
out_register(buf);
|
||||
break;
|
||||
case 4:
|
||||
qsnprintf(buf, sizeof(buf), "*%s-0B",reg);
|
||||
out_register(buf);
|
||||
break;
|
||||
case 5:
|
||||
qsnprintf(buf, sizeof(buf), "*%s-0",reg);
|
||||
out_register(buf);
|
||||
break;
|
||||
case 6:
|
||||
qsnprintf(buf, sizeof(buf), "*%s+0",reg);
|
||||
out_register(buf);
|
||||
break;
|
||||
case 7:
|
||||
qsnprintf(buf, sizeof(buf), "*%s+0B",reg);
|
||||
out_register(buf);
|
||||
break;
|
||||
case 8:
|
||||
qsnprintf(buf, sizeof(buf), "*%s-%%",reg);
|
||||
out_register(buf);
|
||||
break;
|
||||
case 9:
|
||||
qsnprintf(buf, sizeof(buf), "*%s-0%%",reg);
|
||||
out_register(buf);
|
||||
break;
|
||||
case 0xA:
|
||||
qsnprintf(buf, sizeof(buf), "*%s+%%",reg);
|
||||
out_register(buf);
|
||||
break;
|
||||
case 0xB:
|
||||
qsnprintf(buf, sizeof(buf), "*%s+0%%",reg);
|
||||
out_register(buf);
|
||||
break;
|
||||
case 0xC:
|
||||
qsnprintf(buf, sizeof(buf), "*%s(",reg);
|
||||
out_register(buf);
|
||||
out_value(x, OOF_ADDR|OOF_SIGNED|OOFW_16);
|
||||
out_symbol(')');
|
||||
break;
|
||||
case 0xD:
|
||||
qsnprintf(buf, sizeof(buf), "*+%s(",reg);
|
||||
out_register(buf);
|
||||
out_value(x, OOF_ADDR|OOF_SIGNED|OOFW_16);
|
||||
out_symbol(')');
|
||||
break;
|
||||
case 0xE:
|
||||
qsnprintf(buf, sizeof(buf), "*+%s(",reg);
|
||||
out_register(buf);
|
||||
out_value(x, OOF_ADDR|OOF_SIGNED|OOFW_16);
|
||||
out_symbol(')');
|
||||
out_symbol('%');
|
||||
break;
|
||||
// this special adressing mode is now defined as o_farmem !
|
||||
// case ABSOLUTE_INDIRECT_ADRESSING:
|
||||
// out_symbol('*');
|
||||
// out_symbol('(');
|
||||
// out_value(x, OOF_ADDR|OOF_SIGNED|OOFW_16);
|
||||
// out_symbol(')');
|
||||
// break;
|
||||
default:
|
||||
error("interr: out: o_displ");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case o_bit:
|
||||
{
|
||||
if ( !x.NoCardinal )
|
||||
out_symbol('#');
|
||||
char buf[20];
|
||||
qsnprintf(buf, sizeof(buf), "%d", int(x.value));
|
||||
out_line(buf, COLOR_REG);
|
||||
break;
|
||||
}
|
||||
|
||||
case o_cond8:
|
||||
out_cond8((uchar)x.value);
|
||||
break;
|
||||
|
||||
case o_cond2:
|
||||
{
|
||||
const char *cond = "";
|
||||
switch ( x.value )
|
||||
{
|
||||
case 0: cond = "eq"; break;
|
||||
case 1: cond = "lt"; break;
|
||||
case 2: cond = "gt"; break;
|
||||
case 3: cond = "neq"; break;
|
||||
default: warning("interr: out 2-bit condition");
|
||||
}
|
||||
out_line(cond, COLOR_REG);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
error("interr: out");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_tms320c54_t::out_insn(void)
|
||||
{
|
||||
out_mnemonic();
|
||||
out_one_operand(0);
|
||||
if ( insn.Op2.type != o_void )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_char(' ');
|
||||
out_one_operand(1);
|
||||
if ( insn.IsParallel )
|
||||
{ // new line for Parallel instructions
|
||||
flush_outbuf();
|
||||
out_line("|| ", COLOR_INSN);
|
||||
const char *insn2 = NULL;
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case TMS320C54_ld_mac: insn2 = "mac "; break;
|
||||
case TMS320C54_ld_macr: insn2 = "macr "; break;
|
||||
case TMS320C54_ld_mas: insn2 = "mas "; break;
|
||||
case TMS320C54_ld_masr: insn2 = "masr "; break;
|
||||
case TMS320C54_st_add: insn2 = "add "; break;
|
||||
case TMS320C54_st_sub: insn2 = "sub "; break;
|
||||
case TMS320C54_st_ld: insn2 = "ld "; break;
|
||||
case TMS320C54_st_mpy: insn2 = "mpy "; break;
|
||||
case TMS320C54_st_mac: insn2 = "mac "; break;
|
||||
case TMS320C54_st_macr: insn2 = "macr "; break;
|
||||
case TMS320C54_st_mas: insn2 = "mas "; break;
|
||||
case TMS320C54_st_masr: insn2 = "masr "; break;
|
||||
default: warning("interr: out parallel instruction");
|
||||
}
|
||||
out_line(insn2, COLOR_INSN);
|
||||
}
|
||||
if ( insn.Op3.type != o_void )
|
||||
{
|
||||
if ( !insn.IsParallel )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_char(' ');
|
||||
}
|
||||
out_one_operand(2);
|
||||
if ( insn.Op4_type != 0 )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_char(' ');
|
||||
switch ( insn.Op4_type )
|
||||
{
|
||||
case o_reg:
|
||||
out_register(ph.reg_names[insn.Op4_value]);
|
||||
break;
|
||||
case o_cond8:
|
||||
out_cond8(insn.Op4_value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out_immchar_cmts();
|
||||
flush_outbuf();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void tms320c54_t::print_segment_register(outctx_t &ctx, int reg, sel_t value)
|
||||
{
|
||||
if ( reg == ph.reg_data_sreg )
|
||||
return;
|
||||
if ( value != BADADDR )
|
||||
{
|
||||
char buf[MAX_NUMBUF];
|
||||
btoa(buf, sizeof(buf), value);
|
||||
ctx.gen_cmt_line("assume %s = %s", ph.reg_names[reg], buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.gen_cmt_line("drop %s", ph.reg_names[reg]);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// function to produce assume directives
|
||||
//lint -e{1764} ctx could be const
|
||||
void tms320c54_t::assumes(outctx_t &ctx)
|
||||
{
|
||||
ea_t ea = ctx.insn_ea;
|
||||
segment_t *seg = getseg(ea);
|
||||
if ( (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 || seg == NULL )
|
||||
return;
|
||||
bool seg_started = (ea == seg->start_ea);
|
||||
|
||||
for ( int i = ph.reg_first_sreg; i <= ph.reg_last_sreg; ++i )
|
||||
{
|
||||
if ( i == ph.reg_code_sreg )
|
||||
continue;
|
||||
sreg_range_t sra;
|
||||
if ( !get_sreg_range(&sra, ea, i) )
|
||||
continue;
|
||||
if ( seg_started || sra.start_ea == ea )
|
||||
{
|
||||
sel_t now = get_sreg(ea, i);
|
||||
sreg_range_t prev;
|
||||
bool prev_exists = get_sreg_range(&prev, ea-1, i);
|
||||
if ( seg_started || (prev_exists && get_sreg(prev.start_ea, i) != now) )
|
||||
print_segment_register(ctx, i, now);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//lint -e{818} seg could be const
|
||||
void tms320c54_t::segstart(outctx_t &ctx, segment_t *seg) const
|
||||
{
|
||||
if ( is_spec_segm(seg->type) )
|
||||
return;
|
||||
|
||||
qstring sclas;
|
||||
get_segm_class(&sclas, seg);
|
||||
|
||||
if ( sclas == "CODE" )
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR(".text", SCOLOR_ASMDIR));
|
||||
else if ( sclas == "DATA" )
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR(".data", SCOLOR_ASMDIR));
|
||||
|
||||
if ( seg->orgbase != 0 )
|
||||
{
|
||||
char buf[MAX_NUMBUF];
|
||||
btoa(buf, sizeof(buf), seg->orgbase);
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void idaapi segend(outctx_t &, segment_t *)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void idaapi header(outctx_t &ctx)
|
||||
{
|
||||
ctx.gen_header(GH_PRINT_ALL | GH_BYTESEX_HAS_HIGHBYTE);
|
||||
ctx.gen_empty_line();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void tms320c54_t::footer(outctx_t &ctx) const
|
||||
{
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s",SCOLOR_ASMDIR), ash.end);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void tms320c54_t::gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const
|
||||
{
|
||||
char sign = ' ';
|
||||
if ( v < 0 )
|
||||
{
|
||||
sign = '-';
|
||||
v = -v;
|
||||
}
|
||||
|
||||
qstring name = get_member_name(mptr->id);
|
||||
|
||||
char vstr[MAX_NUMBUF];
|
||||
btoa(vstr, sizeof(vstr), v);
|
||||
ctx.out_printf(COLSTR("%s",SCOLOR_KEYWORD) " "
|
||||
COLSTR("%c%s",SCOLOR_DNUM)
|
||||
COLSTR(",",SCOLOR_SYMBOL) " "
|
||||
COLSTR("%s",SCOLOR_LOCNAME),
|
||||
ash.a_equ,
|
||||
sign,
|
||||
vstr,
|
||||
name.c_str());
|
||||
}
|
||||
|
||||
687
idasdk76/module/tms320c54/reg.cpp
Normal file
687
idasdk76/module/tms320c54/reg.cpp
Normal file
@@ -0,0 +1,687 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tms320c54.hpp"
|
||||
#include "notify_codes.hpp"
|
||||
#include <diskio.hpp>
|
||||
#include <segregs.hpp>
|
||||
#include <ieee.h>
|
||||
int data_id;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const char *const register_names[] =
|
||||
{
|
||||
"PC", // program counter
|
||||
"A", // accumulator
|
||||
"B", // accumulator
|
||||
|
||||
// flags
|
||||
"ASM", // 5-bit accumulator shift mode field in ST1
|
||||
"ARP", // auxiliary register pointer
|
||||
"TS", // shift value (bits 5-0 of T)
|
||||
"OVB",
|
||||
"OVA",
|
||||
"C",
|
||||
"TC",
|
||||
"CMPT",
|
||||
"FRCT",
|
||||
"C16",
|
||||
"SXM",
|
||||
"OVM",
|
||||
"INTM",
|
||||
"HM",
|
||||
"XF",
|
||||
"BRAF",
|
||||
|
||||
// CPU memory mapped registers
|
||||
"IMR",
|
||||
"IFR",
|
||||
"ST0",
|
||||
"ST1",
|
||||
"AL",
|
||||
"AH",
|
||||
"AG",
|
||||
"BL",
|
||||
"BH",
|
||||
"BG",
|
||||
"T", // temporary register
|
||||
"TRN", // transition register
|
||||
"AR0",
|
||||
"AR1",
|
||||
"AR2",
|
||||
"AR3",
|
||||
"AR4",
|
||||
"AR5",
|
||||
"AR6",
|
||||
"AR7",
|
||||
"SP", // stack pointer
|
||||
"BK",
|
||||
"BRC",
|
||||
"RSA",
|
||||
"REA",
|
||||
"PMST",
|
||||
|
||||
// segment registers
|
||||
"XPC", // program counter extension register
|
||||
"CPL", // compiler mode
|
||||
"DP", // data page pointer
|
||||
"cs","ds", // virtual registers for code and data segments
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const uchar retcode_0[] = { 0xF4, 0xE4 }; // fret
|
||||
static const uchar retcode_1[] = { 0xF6, 0xE4 }; // fretd
|
||||
static const uchar retcode_2[] = { 0xF4, 0xE5 }; // frete
|
||||
static const uchar retcode_3[] = { 0xF6, 0xE5 }; // freted
|
||||
static const uchar retcode_4[] = { 0xFC }; // rc
|
||||
static const uchar retcode_5[] = { 0xFE }; // rcd
|
||||
static const uchar retcode_6[] = { 0xFC, 0x00 }; // ret
|
||||
static const uchar retcode_7[] = { 0xFE, 0x00 }; // retd
|
||||
static const uchar retcode_8[] = { 0xF4, 0xEA }; // rete
|
||||
static const uchar retcode_9[] = { 0xF6, 0xEA }; // reted
|
||||
static const uchar retcode_10[] = { 0xF4, 0x9A }; // retf
|
||||
static const uchar retcode_11[] = { 0xF6, 0x9A }; // retfd
|
||||
|
||||
static const bytes_t retcodes[] =
|
||||
{
|
||||
{ sizeof(retcode_0), retcode_0 },
|
||||
{ sizeof(retcode_1), retcode_1 },
|
||||
{ sizeof(retcode_2), retcode_2 },
|
||||
{ sizeof(retcode_3), retcode_3 },
|
||||
{ sizeof(retcode_4), retcode_4 },
|
||||
{ sizeof(retcode_5), retcode_5 },
|
||||
{ sizeof(retcode_6), retcode_6 },
|
||||
{ sizeof(retcode_7), retcode_7 },
|
||||
{ sizeof(retcode_8), retcode_8 },
|
||||
{ sizeof(retcode_9), retcode_9 },
|
||||
{ sizeof(retcode_10), retcode_10 },
|
||||
{ sizeof(retcode_11), retcode_11 },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// TMS320C54 ASM
|
||||
//-----------------------------------------------------------------------
|
||||
static const asm_t fasm =
|
||||
{
|
||||
AS_N2CHR|ASH_HEXF0|ASD_DECF0|ASO_OCTF5|ASB_BINF0|AS_ONEDUP|AS_COLON,
|
||||
0,
|
||||
"ASM500",
|
||||
0,
|
||||
NULL, // header lines
|
||||
NULL, // org
|
||||
".end", // end
|
||||
|
||||
";", // comment string
|
||||
'"', // string delimiter
|
||||
'\'', // char delimiter
|
||||
"'\"", // special symbols in char and string constants
|
||||
|
||||
".pstring", // ascii string directive
|
||||
".word", // byte directive
|
||||
".long", // word directive
|
||||
NULL, // double words
|
||||
NULL, // qwords
|
||||
NULL, // oword (16 bytes)
|
||||
".float", // float (4 bytes)
|
||||
NULL, // double (8 bytes)
|
||||
NULL, // tbyte (10/12 bytes)
|
||||
NULL, // packed decimal real
|
||||
NULL, // arrays (#h,#d,#v,#s(...)
|
||||
".space 16*%s",// uninited arrays
|
||||
".asg", // equ
|
||||
NULL, // 'seg' prefix (example: push seg seg001)
|
||||
"$", // current IP (instruction pointer)
|
||||
NULL, // func_header
|
||||
NULL, // func_footer
|
||||
".global", // "public" name keyword
|
||||
NULL, // "weak" name keyword
|
||||
".ref", // "extrn" name keyword
|
||||
NULL, // "comm" (communal variable)
|
||||
NULL, // get_type_name
|
||||
".align", // "align" keyword
|
||||
'(', ')', // lbrace, rbrace
|
||||
"%", // mod
|
||||
"&", // and
|
||||
"|", // or
|
||||
"^", // xor
|
||||
"~", // not
|
||||
"<<", // shl
|
||||
">>", // shr
|
||||
NULL, // sizeof
|
||||
AS2_STRINV // invert string byte order
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// GNU ASM
|
||||
//-----------------------------------------------------------------------
|
||||
static const asm_t gnuasm =
|
||||
{
|
||||
AS_N2CHR|ASH_HEXF3|ASD_DECF0|ASO_OCTF5|ASB_BINF0|AS_ONEDUP|AS_COLON|AS_ASCIIC,
|
||||
0,
|
||||
"GNU assembler",
|
||||
0,
|
||||
NULL, // header lines
|
||||
NULL, // org
|
||||
".end", // end
|
||||
|
||||
";", // comment string
|
||||
'"', // string delimiter
|
||||
'\'', // char delimiter
|
||||
"'\"", // special symbols in char and string constants
|
||||
|
||||
".pstring", // ascii string directive
|
||||
".word", // byte directive
|
||||
".long", // word directive
|
||||
NULL, // double words
|
||||
NULL, // qwords
|
||||
NULL, // oword (16 bytes)
|
||||
".float", // float (4 bytes)
|
||||
NULL, // double (8 bytes)
|
||||
NULL, // tbyte (10/12 bytes)
|
||||
NULL, // packed decimal real
|
||||
NULL, // arrays (#h,#d,#v,#s(...)
|
||||
".zero 2*%s", // uninited arrays
|
||||
".asg", // equ
|
||||
NULL, // 'seg' prefix (example: push seg seg001)
|
||||
"$", // current IP (instruction pointer)
|
||||
NULL, // func_header
|
||||
NULL, // func_footer
|
||||
".global", // "public" name keyword
|
||||
".weak", // "weak" name keyword
|
||||
".extern", // "extrn" name keyword
|
||||
NULL, // "comm" (communal variable)
|
||||
NULL, // get_type_name
|
||||
".align", // "align" keyword
|
||||
'(', ')', // lbrace, rbrace
|
||||
"%", // mod
|
||||
"&", // and
|
||||
"|", // or
|
||||
"^", // xor
|
||||
"~", // not
|
||||
"<<", // shl
|
||||
">>", // shr
|
||||
NULL, // sizeof
|
||||
AS2_STRINV, // invert string byte order
|
||||
NULL, // cmnt2
|
||||
NULL, // low8
|
||||
NULL, // high8
|
||||
NULL, // low16
|
||||
NULL, // high16
|
||||
"#include \"%s\"", // a_include_fmt
|
||||
};
|
||||
|
||||
static const asm_t *const asms[] = { &fasm, &gnuasm, NULL };
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
const char *tms320c54_t::find_sym(ea_t address)
|
||||
{
|
||||
const ioport_t *port = find_ioport(ioh.ports, address);
|
||||
return port ? port->name.c_str() : NULL;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void tms320c54_t::apply_symbols(void)
|
||||
{
|
||||
insn_t dummy;
|
||||
for ( int i=0; i < ioh.ports.size(); i++ )
|
||||
{
|
||||
ea_t ea = calc_data_mem(dummy, ioh.ports[i].address, false);
|
||||
segment_t *s = getseg(ea);
|
||||
if ( s == NULL || s->type != SEG_IMEM )
|
||||
continue;
|
||||
create_byte(ea, 1);
|
||||
const char *name = ioh.ports[i].name.c_str();
|
||||
if ( !set_name(ea, name, SN_NOCHECK|SN_NOWARN|SN_NODUMMY) )
|
||||
set_cmt(ea, name, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline void swap(unsigned char &c1, unsigned char &c2)
|
||||
{
|
||||
unsigned char tmp = c1;
|
||||
c1 = c2;
|
||||
c2 = tmp;
|
||||
}
|
||||
|
||||
fpvalue_error_t idaapi tms_realcvt(void *m, fpvalue_t *e, ushort swt)
|
||||
{
|
||||
fpvalue_error_t ret;
|
||||
switch ( swt )
|
||||
{
|
||||
case 1: // float to e
|
||||
{
|
||||
unsigned char p[4];
|
||||
memcpy(p, m, 4);
|
||||
swap(p[0], p[1]);
|
||||
swap(p[2], p[3]);
|
||||
ret = ieee_realcvt(p, e, swt);
|
||||
break;
|
||||
}
|
||||
case 011: // float output //-V536 octal
|
||||
{
|
||||
ret = ieee_realcvt(m, e, swt);
|
||||
unsigned char *p = (unsigned char*)m;
|
||||
swap(p[0], p[1]);
|
||||
swap(p[2], p[3]);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ret = ieee_realcvt(m, e, swt);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static int idaapi choose_device(int, form_actions_t &fa)
|
||||
{
|
||||
tms320c54_t &pm = *(tms320c54_t *)fa.get_ud();
|
||||
if ( choose_ioport_device(&pm.ioh.device, cfgname) )
|
||||
pm.ioh.set_device_name(pm.ioh.device.c_str(), IORESP_ALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
const char *tms320c54_t::set_idp_options(
|
||||
const char *keyword,
|
||||
int value_type,
|
||||
const void * value,
|
||||
bool idb_loaded)
|
||||
{
|
||||
if ( keyword == NULL )
|
||||
{
|
||||
static const char form[] =
|
||||
"HELP\n"
|
||||
"TMS320C54 specific options\n"
|
||||
"\n"
|
||||
" Use I/O definitions\n"
|
||||
"\n"
|
||||
" If this option is on, IDA will use I/O definitions\n"
|
||||
" from the configuration file into a macro instruction.\n"
|
||||
"\n"
|
||||
" Detect memory mapped registers\n"
|
||||
"\n"
|
||||
" If this option is on, IDA will replace addresses\n"
|
||||
" by an equivalent memory mapped register.\n"
|
||||
"\n"
|
||||
" Device name\n"
|
||||
"\n"
|
||||
" Choose the exact device name for the processor.\n"
|
||||
" If you don't see the name you want, you can add\n"
|
||||
" a section about it to the tms320c54.cfg file\n"
|
||||
"\n"
|
||||
" Data segment address\n"
|
||||
"\n"
|
||||
" The data segment linear address.\n"
|
||||
"\n"
|
||||
"ENDHELP\n"
|
||||
"TMS320C54 specific options\n"
|
||||
"%*\n"
|
||||
" <Use ~I~/O definitions:C>\n"
|
||||
" <Detect memory mapped ~r~egisters:C>>\n"
|
||||
"\n"
|
||||
" <~C~hoose device name:B:0:::>\n"
|
||||
"\n"
|
||||
" <~D~ata segment address:N::18::>\n"
|
||||
"\n";
|
||||
CASSERT(sizeof(idpflags) == sizeof(ushort));
|
||||
CASSERT(sizeof(dataseg) == sizeof(ea_t));
|
||||
ask_form(form, this, &idpflags, choose_device, &dataseg);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( strcmp(keyword, "TMS320C54_DSEG") == 0 )
|
||||
{
|
||||
if ( value_type != IDPOPT_NUM )
|
||||
return IDPOPT_BADTYPE;
|
||||
dataseg = *(uval_t *)value;
|
||||
}
|
||||
if ( value_type != IDPOPT_BIT )
|
||||
return IDPOPT_BADTYPE;
|
||||
if ( strcmp(keyword, "TMS320C54_IO") == 0 )
|
||||
{
|
||||
setflag(idpflags, TMS320C54_IO, *(int*)value != 0);
|
||||
}
|
||||
else if ( strcmp(keyword, "TMS320C54_MMR") == 0 )
|
||||
{
|
||||
setflag(idpflags, TMS320C54_MMR, *(int*)value != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return IDPOPT_BADKEY;
|
||||
}
|
||||
}
|
||||
if ( idb_loaded )
|
||||
{
|
||||
save_idpflags();
|
||||
save_dataseg();
|
||||
}
|
||||
return IDPOPT_OK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const proctype_t ptypes[] =
|
||||
{
|
||||
TMS320C54
|
||||
};
|
||||
|
||||
void tms320c54_t::load_from_idb()
|
||||
{
|
||||
ptype = ptypes[ph.get_proc_index()];
|
||||
ioh.restore_device();
|
||||
if ( ioh.device.empty() )
|
||||
{
|
||||
read_ioports(&ioh.ports, &ioh.device, cfgname);
|
||||
helper.supset(-1, ioh.device.c_str());
|
||||
}
|
||||
inf_set_wide_high_byte_first(false);
|
||||
idpflags = (ushort)helper.altval(-1);
|
||||
dataseg = helper.altval(0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// This old-style callback only returns the processor module object.
|
||||
static ssize_t idaapi notify(void *, int msgid, va_list)
|
||||
{
|
||||
if ( msgid == processor_t::ev_get_procmod )
|
||||
return size_t(SET_MODULE_DATA(tms320c54_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
ssize_t idaapi tms320c54_t::on_event(ssize_t msgid, va_list va)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4063)
|
||||
#endif
|
||||
int code = 0;
|
||||
switch ( msgid ) // Cast to avoid lint complaining.
|
||||
{
|
||||
case processor_t::ev_init:
|
||||
helper.create(PROCMOD_NODE_NAME);
|
||||
inf_set_be(true); // MSB first
|
||||
inf_set_wide_high_byte_first(true);
|
||||
dataseg = helper.altval(0);
|
||||
break;
|
||||
|
||||
case processor_t::ev_term:
|
||||
ioh.ports.clear();
|
||||
clr_module_data(data_id);
|
||||
break;
|
||||
|
||||
case processor_t::ev_newfile: // new file loaded
|
||||
read_ioports(&ioh.ports, &ioh.device, cfgname);
|
||||
helper.supset(-1, ioh.device.c_str());
|
||||
save_idpflags();
|
||||
save_dataseg();
|
||||
inf_set_wide_high_byte_first(false);
|
||||
{
|
||||
segment_t *s = get_first_seg();
|
||||
if ( s != NULL )
|
||||
apply_symbols();
|
||||
while ( s != NULL )
|
||||
{
|
||||
qstring sclas;
|
||||
get_segm_class(&sclas, s);
|
||||
for ( int i = XPC; i <= rVds; i++ )
|
||||
set_default_sreg_value(s, i, BADSEL);
|
||||
if ( sclas == "CODE" )
|
||||
set_default_sreg_value(s, XPC, s->start_ea >> 16);
|
||||
s = get_next_seg(s->start_ea);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case tms320c54_module_t::ev_set_dataseg:
|
||||
dataseg = va_arg(va, ea_t);
|
||||
save_dataseg();
|
||||
break;
|
||||
|
||||
case processor_t::ev_oldfile: // old file loaded
|
||||
ioh.upgrade_device_index();
|
||||
//fall through
|
||||
case processor_t::ev_ending_undo:
|
||||
load_from_idb();
|
||||
break;
|
||||
|
||||
case processor_t::ev_newbinary:
|
||||
inf_set_wide_high_byte_first(true);
|
||||
break;
|
||||
case processor_t::ev_endbinary:
|
||||
inf_set_wide_high_byte_first(false);
|
||||
break;
|
||||
|
||||
case processor_t::ev_newprc: // new processor type
|
||||
{
|
||||
ptype = ptypes[va_arg(va, int)];
|
||||
// bool keep_cfg = va_argi(va, bool);
|
||||
switch ( ptype )
|
||||
{
|
||||
case TMS320C54:
|
||||
break;
|
||||
default:
|
||||
error("interr: setprc");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case processor_t::ev_newasm: // new assembler type
|
||||
break;
|
||||
|
||||
case processor_t::ev_creating_segm: // new segment
|
||||
break;
|
||||
|
||||
case processor_t::ev_is_basic_block_end:
|
||||
{
|
||||
const insn_t *insn = va_arg(va, const insn_t *);
|
||||
return is_basic_block_end(*insn) ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_is_sane_insn:
|
||||
{
|
||||
const insn_t *insn = va_arg(va, const insn_t *);
|
||||
int no_crefs = va_arg(va, int);
|
||||
// add 0, a is not a sane instruction without crefs to it
|
||||
code = no_crefs && get_wide_byte(insn->ea) == 0 ? -1 : 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case processor_t::ev_out_header:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
header(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_footer:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
footer(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_segstart:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
segment_t *seg = va_arg(va, segment_t *);
|
||||
segstart(*ctx, seg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_segend:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
segment_t *seg = va_arg(va, segment_t *);
|
||||
segend(*ctx, seg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_assumes:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
assumes(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_ana_insn:
|
||||
{
|
||||
insn_t *out = va_arg(va, insn_t *);
|
||||
return ana(out);
|
||||
}
|
||||
|
||||
case processor_t::ev_emu_insn:
|
||||
{
|
||||
const insn_t *insn = va_arg(va, const insn_t *);
|
||||
return emu(*insn) ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_insn:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
out_insn(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_operand:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
const op_t *op = va_arg(va, const op_t *);
|
||||
return out_opnd(*ctx, *op) ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_realcvt:
|
||||
{
|
||||
void *m = va_arg(va, void *);
|
||||
fpvalue_t *e = va_arg(va, fpvalue_t *);
|
||||
uint16 swt = va_argi(va, uint16);
|
||||
fpvalue_error_t code1 = tms_realcvt(m, e, swt);
|
||||
return code1 == REAL_ERROR_OK ? 1 : code1;
|
||||
}
|
||||
|
||||
case processor_t::ev_create_func_frame:
|
||||
{
|
||||
func_t *pfn = va_arg(va, func_t *);
|
||||
create_func_frame(pfn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_get_frame_retsize:
|
||||
{
|
||||
int *frsize = va_arg(va, int *);
|
||||
const func_t *pfn = va_arg(va, const func_t *);
|
||||
*frsize = tms_get_frame_retsize(pfn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_gen_stkvar_def:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
const member_t *mptr = va_arg(va, const member_t *);
|
||||
sval_t v = va_arg(va, sval_t);
|
||||
gen_stkvar_def(*ctx, mptr, v);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_set_idp_options:
|
||||
{
|
||||
const char *keyword = va_arg(va, const char *);
|
||||
int value_type = va_arg(va, int);
|
||||
const char *value = va_arg(va, const char *);
|
||||
const char **errmsg = va_arg(va, const char **);
|
||||
bool idb_loaded = va_argi(va, bool);
|
||||
const char *ret = set_idp_options(keyword, value_type, value, idb_loaded);
|
||||
if ( ret == IDPOPT_OK )
|
||||
return 1;
|
||||
if ( errmsg != NULL )
|
||||
*errmsg = ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_is_align_insn:
|
||||
{
|
||||
ea_t ea = va_arg(va, ea_t);
|
||||
return is_align_insn(ea);
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
return code;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
#define FAMILY "TMS320C54x Series:"
|
||||
static const char *const shnames[] =
|
||||
{
|
||||
"TMS32054",
|
||||
NULL
|
||||
};
|
||||
static const char *const lnames[] =
|
||||
{
|
||||
FAMILY"Texas Instruments TMS320C54",
|
||||
NULL
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Processor Definition
|
||||
//-----------------------------------------------------------------------
|
||||
processor_t LPH =
|
||||
{
|
||||
IDP_INTERFACE_VERSION, // version
|
||||
PLFM_TMS320C54, // id
|
||||
// flag
|
||||
PRN_HEX
|
||||
| PR_SEGS
|
||||
| PR_SGROTHER
|
||||
| PR_ALIGN,
|
||||
// flag2
|
||||
PR2_MAPPINGS // use memory mapping
|
||||
| PR2_REALCVT // the module has 'realcvt' event implementation
|
||||
| PR2_IDP_OPTS, // the module has processor-specific configuration options
|
||||
16, // 16 bits in a byte for code segments
|
||||
16, // 16 bits in a byte for other segments
|
||||
|
||||
shnames,
|
||||
lnames,
|
||||
|
||||
asms,
|
||||
|
||||
notify,
|
||||
|
||||
register_names, // Register names
|
||||
qnumber(register_names), // Number of registers
|
||||
|
||||
XPC, // first
|
||||
rVds, // last
|
||||
1, // size of a segment register
|
||||
rVcs, rVds,
|
||||
|
||||
NULL, // No known code start sequences
|
||||
retcodes,
|
||||
|
||||
TMS320C54_null,
|
||||
TMS320C54_last,
|
||||
Instructions, // instruc
|
||||
0, // int tbyte_size; -- doesn't exist
|
||||
{ 0,7,15,19 }, // char real_width[4];
|
||||
// number of symbols after decimal point
|
||||
// 2byte float (0-does not exist)
|
||||
// normal float
|
||||
// normal double
|
||||
// long double
|
||||
TMS320C54_ret, // Icode of return instruction. It is ok to give any of possible return instructions
|
||||
};
|
||||
200
idasdk76/module/tms320c54/tms320c54.cfg
Normal file
200
idasdk76/module/tms320c54/tms320c54.cfg
Normal file
@@ -0,0 +1,200 @@
|
||||
;
|
||||
; This file defines SFR names and bit names for TMS320C54 processors.
|
||||
;
|
||||
; This file can be configured for different devices.
|
||||
; At the beginning of the file there are definitions common for all devices
|
||||
; Device-specific definitions are introduced by
|
||||
;
|
||||
; .devicename
|
||||
;
|
||||
; line. Also an optional directive
|
||||
;
|
||||
; .default=devicename
|
||||
;
|
||||
; designates the default device name.
|
||||
;
|
||||
|
||||
.default C541
|
||||
|
||||
OUTDAT 0x7
|
||||
INDAT 0x60
|
||||
|
||||
TEST 0xFCFDFEFF
|
||||
|
||||
;-------------------------------
|
||||
; Device specific definitions
|
||||
|
||||
.C542
|
||||
|
||||
; insert definitions here
|
||||
|
||||
.C543
|
||||
|
||||
; insert definitions here
|
||||
|
||||
.C544
|
||||
|
||||
; insert definitions here
|
||||
|
||||
.C545
|
||||
|
||||
; insert definitions here
|
||||
|
||||
.C546
|
||||
|
||||
; insert definitions here
|
||||
|
||||
.C548
|
||||
|
||||
; insert definitions here
|
||||
|
||||
.C549
|
||||
|
||||
; insert definitions here
|
||||
|
||||
.C5402
|
||||
|
||||
; insert definitions here
|
||||
|
||||
.C5410
|
||||
|
||||
; insert definitions here
|
||||
|
||||
.C5420
|
||||
|
||||
; insert definitions here
|
||||
|
||||
.CALYPSO
|
||||
|
||||
; entry _reset 0xff80 Reset vector
|
||||
|
||||
; RIF
|
||||
RIF_DXR 0x0000
|
||||
RIF_DRR 0x0001
|
||||
RIF_SPCX 0x0002
|
||||
RIF_SPCR 0x0003
|
||||
|
||||
; CYPHER
|
||||
CYPHER_CNTL 0x2800
|
||||
CYPHER_CNTL.START 0
|
||||
CYPHER_CNTL.RESETSW 1
|
||||
CYPHER_CNTL.MODE0 2
|
||||
CYPHER_CNTL.MODE1 3
|
||||
CYPHER_CNTL.CLK_EN 4
|
||||
CYPHER_CNTL.CYPHER_ONLY 5
|
||||
|
||||
CYPHER_STATUS_IRQ 0x2801
|
||||
CYPHER_STATUS_IRQ.LT_FIN 0
|
||||
|
||||
CYPHER_STATUS_WORK 0x2802
|
||||
CYPHER_STATUS_WORK.WORKING 0
|
||||
|
||||
CYPHER_KC_1 0x2803
|
||||
CYPHER_KC_2 0x2804
|
||||
CYPHER_KC_3 0x2805
|
||||
CYPHER_KC_4 0x2806
|
||||
CYPHER_COUNT_1 0x2807
|
||||
CYPHER_COUNT_2 0x2808
|
||||
CYPHER_DECI_1 0x2809
|
||||
CYPHER_DECI_2 0x280A
|
||||
CYPHER_DECI_3 0x280B
|
||||
CYPHER_DECI_4 0x280C
|
||||
CYPHER_DECI_5 0x280D
|
||||
CYPHER_DECI_6 0x280E
|
||||
CYPHER_DECI_7 0x280F
|
||||
CYPHER_DECI_8 0x2810
|
||||
CYPHER_ENCI_1 0x2811
|
||||
CYPHER_ENCI_2 0x2812
|
||||
CYPHER_ENCI_3 0x2813
|
||||
CYPHER_ENCI_4 0x2814
|
||||
CYPHER_ENCI_5 0x2815
|
||||
CYPHER_ENCI_6 0x2816
|
||||
CYPHER_ENCI_7 0x2817
|
||||
CYPHER_ENCI_8 0x2818
|
||||
|
||||
; MCSI
|
||||
MCSI_CONTROL 0x0800
|
||||
MCSI_MAIN-PARAMETERS 0x0801
|
||||
MCSI_INTERRUPTS 0x0802
|
||||
MCSI_CHANNEL-USED 0x0803
|
||||
MCSI_OVER-CLK 0x0804
|
||||
MCSI_CLK-FREQ 0x0805
|
||||
MCSI_STATUS 0x0806
|
||||
MCSI_TX0 0x0820
|
||||
MCSI_TX1 0x0821
|
||||
MCSI_TX2 0x0822
|
||||
MCSI_TX3 0x0823
|
||||
MCSI_TX4 0x0824
|
||||
MCSI_TX5 0x0825
|
||||
MCSI_TX6 0x0826
|
||||
MCSI_TX7 0x0827
|
||||
MCSI_TX8 0x0828
|
||||
MCSI_TX9 0x0829
|
||||
MCSI_TX10 0x082A
|
||||
MCSI_TX11 0x082B
|
||||
MCSI_TX12 0x082C
|
||||
MCSI_TX13 0x082D
|
||||
MCSI_TX14 0x082E
|
||||
MCSI_TX15 0x082F
|
||||
MCSI_RX0 0x0830
|
||||
MCSI_RX1 0x0831
|
||||
MCSI_RX2 0x0832
|
||||
MCSI_RX3 0x0833
|
||||
MCSI_RX4 0x0834
|
||||
MCSI_RX5 0x0835
|
||||
MCSI_RX6 0x0836
|
||||
MCSI_RX7 0x0837
|
||||
MCSI_RX8 0x0838
|
||||
MCSI_RX9 0x0839
|
||||
MCSI_RX10 0x083A
|
||||
MCSI_RX11 0x083B
|
||||
MCSI_RX12 0x083C
|
||||
MCSI_RX13 0x083D
|
||||
MCSI_RX14 0x083E
|
||||
MCSI_RX15 0x083F
|
||||
|
||||
; RHEA
|
||||
RHEA_TRANSFER_RATE 0xF800
|
||||
|
||||
RHEA_BRIDGE-CTRL 0xF801
|
||||
RHEA_BRIDGE-CTRL.TIMEOUT_ENABLE 8
|
||||
RHEA_BRIDGE-CTRL.NSUPV 9
|
||||
|
||||
; API
|
||||
API_CONF 0xF900
|
||||
API_CONF.RESERVED0 0
|
||||
API_CONF.API_HOM 1
|
||||
API_CONF.BRIDGE_CLK_EN 2
|
||||
|
||||
; Interrupts
|
||||
INT_CNTRL 0xFA00
|
||||
INT_CLEAR 0xFA01
|
||||
|
||||
; DMA
|
||||
DMA_CONTROLLER_CONF 0xFC00
|
||||
DMA_ALLOC_CONFIG 0xFC02
|
||||
DMA1_RAD 0xFC10
|
||||
DMA1_RDPTH 0xFC12
|
||||
DMA1_AAD 0xFC14
|
||||
DMA1_ALGTH 0xFC16
|
||||
DMA1_CTRL 0xFC18
|
||||
DMA1_CUR_OFFSET_API 0xFC1A
|
||||
DMA2_RAD 0xFC20
|
||||
DMA2_RDPTH 0xFC22
|
||||
DMA2_AAD 0xFC24
|
||||
DMA2_ALGTH 0xFC26
|
||||
DMA2_CTRL 0xFC28
|
||||
DMA2_CUR_OFFSET_API 0xFC2A
|
||||
DMA3_RAD 0xFC30
|
||||
DMA3_RDPTH 0xFC32
|
||||
DMA3_AAD 0xFC34
|
||||
DMA3_ALGTH 0xFC36
|
||||
DMA3_CTRL 0xFC38
|
||||
DMA3_CUR_OFFSET_API 0xFC3A
|
||||
DMA4_RAD 0xFC40
|
||||
DMA4_RDPTH 0xFC42
|
||||
DMA4_AAD 0xFC44
|
||||
DMA4_ALGTH 0xFC46
|
||||
DMA4_CTRL 0xFC48
|
||||
DMA4_CUR_OFFSET_API 0xFC4A
|
||||
|
||||
243
idasdk76/module/tms320c54/tms320c54.hpp
Normal file
243
idasdk76/module/tms320c54/tms320c54.hpp
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TMS320C54_HPP
|
||||
#define _TMS320C54_HPP
|
||||
|
||||
#include "../idaidp.hpp"
|
||||
#include <diskio.hpp>
|
||||
#include "ins.hpp"
|
||||
#include "../iohandler.hpp"
|
||||
|
||||
|
||||
// #define TMS320C54_NO_NAME_NO_REF
|
||||
|
||||
//------------------------------------------------------------------
|
||||
#ifdef _MSC_VER
|
||||
#define ENUM8BIT : uint8
|
||||
#else
|
||||
#define ENUM8BIT
|
||||
#endif
|
||||
enum regnum_t ENUM8BIT
|
||||
{
|
||||
PC, // program counter
|
||||
A, // accumulator
|
||||
B, // accumulator
|
||||
|
||||
// flags
|
||||
ASM, // 5-bit accumulator shift mode field in ST1
|
||||
ARP, // auxiliary register pointer
|
||||
TS, // shift value (bits 5-0 of T)
|
||||
OVB,
|
||||
OVA,
|
||||
C,
|
||||
TC,
|
||||
CMPT,
|
||||
FRCT,
|
||||
C16,
|
||||
SXM,
|
||||
OVM,
|
||||
INTM,
|
||||
HM,
|
||||
XF,
|
||||
BRAF,
|
||||
|
||||
// CPU memory mapped registers
|
||||
IMR,
|
||||
IFR,
|
||||
ST0,
|
||||
ST1,
|
||||
AL,
|
||||
AH,
|
||||
AG,
|
||||
BL,
|
||||
BH,
|
||||
BG,
|
||||
T, // temporary register
|
||||
TRN, // transition register
|
||||
AR0,
|
||||
AR1,
|
||||
AR2,
|
||||
AR3,
|
||||
AR4,
|
||||
AR5,
|
||||
AR6,
|
||||
AR7,
|
||||
SP, // stack pointer
|
||||
BK,
|
||||
BRC,
|
||||
RSA,
|
||||
REA,
|
||||
PMST,
|
||||
|
||||
// segment registers
|
||||
XPC, // program counter extension register
|
||||
CPL, // compiler mode
|
||||
DP, // data page pointer
|
||||
rVcs, rVds, // virtual registers for code and data segments
|
||||
rnone = 0xFF, // no register
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// specific condition codes
|
||||
#define COND_A 0x0
|
||||
#define COND_B 0x8
|
||||
|
||||
#define COND_GEQ 0x2
|
||||
#define COND_LT 0x3
|
||||
#define COND_NEQ 0x4
|
||||
#define COND_EQ 0x5
|
||||
#define COND_GT 0x6
|
||||
#define COND_LEQ 0x7
|
||||
|
||||
|
||||
#define COND4_AGEQ (COND_A | COND_GEQ)
|
||||
#define COND4_ALT (COND_A | COND_LT)
|
||||
#define COND4_ANEQ (COND_A | COND_NEQ)
|
||||
#define COND4_AEQ (COND_A | COND_EQ)
|
||||
#define COND4_AGT (COND_A | COND_GT)
|
||||
#define COND4_ALEQ (COND_A | COND_LEQ)
|
||||
|
||||
#define COND4_BGEQ (COND_B | COND_GEQ)
|
||||
#define COND4_BLT (COND_B | COND_LT)
|
||||
#define COND4_BNEQ (COND_B | COND_NEQ)
|
||||
#define COND4_BEQ (COND_B | COND_EQ)
|
||||
#define COND4_BGT (COND_B | COND_GT)
|
||||
#define COND4_BLEQ (COND_B | COND_LEQ)
|
||||
|
||||
|
||||
#define COND8_FROM_COND4 0x40
|
||||
|
||||
#define COND8_UNC 0x00
|
||||
#define COND8_NBIO 0x02
|
||||
#define COND8_BIO 0x03
|
||||
#define COND8_NC 0x08
|
||||
#define COND8_C 0x0C
|
||||
#define COND8_NTC 0x20
|
||||
#define COND8_TC 0x30
|
||||
#define COND8_AGEQ (COND8_FROM_COND4 | COND4_AGEQ)
|
||||
#define COND8_ALT (COND8_FROM_COND4 | COND4_ALT)
|
||||
#define COND8_ANEQ (COND8_FROM_COND4 | COND4_ANEQ)
|
||||
#define COND8_AEQ (COND8_FROM_COND4 | COND4_AEQ)
|
||||
#define COND8_AGT (COND8_FROM_COND4 | COND4_AGT)
|
||||
#define COND8_ALEQ (COND8_FROM_COND4 | COND4_ALEQ)
|
||||
#define COND8_ANOV 0x60
|
||||
#define COND8_AOV 0x70
|
||||
#define COND8_BGEQ (COND8_FROM_COND4 | COND4_BGEQ)
|
||||
#define COND8_BLT (COND8_FROM_COND4 | COND4_BLT)
|
||||
#define COND8_BNEQ (COND8_FROM_COND4 | COND4_BNEQ)
|
||||
#define COND8_BEQ (COND8_FROM_COND4 | COND4_BEQ)
|
||||
#define COND8_BGT (COND8_FROM_COND4 | COND4_BGT)
|
||||
#define COND8_BLEQ (COND8_FROM_COND4 | COND4_BLEQ)
|
||||
#define COND8_BNOV (COND_B | COND8_ANOV)
|
||||
#define COND8_BOV (COND_B | COND8_AOV)
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// specific processor records
|
||||
|
||||
#define o_bit o_idpspec0
|
||||
#define o_cond8 o_idpspec1
|
||||
#define o_cond2 o_idpspec2
|
||||
#define o_local o_idpspec3
|
||||
#define o_mmr o_idpspec4
|
||||
#define o_farmem o_idpspec5
|
||||
|
||||
#define Op4_type auxpref_u8[0]
|
||||
#define Op4_value auxpref_u8[1]
|
||||
#define IsParallel segpref
|
||||
|
||||
// != 0 => MOD = IndirectAddressingMOD-1
|
||||
#define IndirectAddressingMOD specflag1
|
||||
#define ABSOLUTE_INDIRECT_ADRESSING 0xF // special "indirect" adressing
|
||||
// (in fact absolute adressing)
|
||||
#define Signed specflag1
|
||||
#define NoCardinal specflag2
|
||||
#define IOimm specflag3
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// processor types
|
||||
|
||||
typedef uchar proctype_t;
|
||||
|
||||
const proctype_t TMS320C54 = 0;
|
||||
|
||||
#define TMS320C54_IO 0x0001 // use I/O definitions
|
||||
#define TMS320C54_MMR 0x0002 // use memory mapped registers
|
||||
|
||||
//------------------------------------------------------------------
|
||||
const char *const cfgname = "tms320c54.cfg";
|
||||
|
||||
struct tms320c54_iohandler_t : public iohandler_t
|
||||
{
|
||||
tms320c54_iohandler_t(netnode &nn) : iohandler_t(nn) {}
|
||||
void get_cfg_filename(char *buf, size_t bufsize) override
|
||||
{
|
||||
qstrncpy(buf, cfgname, bufsize);
|
||||
}
|
||||
};
|
||||
|
||||
struct tms320c54_t : public procmod_t
|
||||
{
|
||||
netnode helper;
|
||||
tms320c54_iohandler_t ioh = tms320c54_iohandler_t(helper);
|
||||
|
||||
ea_t dataseg;
|
||||
ushort idpflags = TMS320C54_IO|TMS320C54_MMR;
|
||||
proctype_t ptype = TMS320C54;
|
||||
bool flow = false;
|
||||
|
||||
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
|
||||
|
||||
const char *find_sym(ea_t address);
|
||||
void apply_symbols(void);
|
||||
const char *idaapi set_idp_options(
|
||||
const char *keyword,
|
||||
int value_type,
|
||||
const void * value,
|
||||
bool idb_loaded);
|
||||
|
||||
int ana(insn_t *insn);
|
||||
|
||||
int emu(const insn_t &insn);
|
||||
void handle_operand(const insn_t &insn, const op_t &x, flags_t F, bool use);
|
||||
ea_t calc_data_mem(const insn_t &insn, ea_t ea, bool is_mem) const;
|
||||
bool create_func_frame(func_t *pfn) const;
|
||||
regnum_t get_mapped_register(ea_t ea) const;
|
||||
|
||||
void assumes(outctx_t &ctx);
|
||||
void print_segment_register(outctx_t &ctx, int reg, sel_t value);
|
||||
void segstart(outctx_t &ctx, segment_t *seg) const;
|
||||
void footer(outctx_t &ctx) const;
|
||||
void gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const;
|
||||
|
||||
void save_idpflags() { helper.altset(-1, idpflags); }
|
||||
void save_dataseg() { helper.altset(0, dataseg); }
|
||||
void load_from_idb();
|
||||
};
|
||||
|
||||
extern int data_id;
|
||||
#define PROCMOD_NODE_NAME "$ tms320c54"
|
||||
#define PROCMOD_NAME tms320c54
|
||||
|
||||
ea_t calc_code_mem(const insn_t &insn, ea_t ea, bool is_near = true);
|
||||
|
||||
const char *get_cond8(char value);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
void idaapi header(outctx_t &ctx);
|
||||
|
||||
void idaapi segend(outctx_t &ctx, segment_t *seg);
|
||||
|
||||
void idaapi data(ea_t ea);
|
||||
|
||||
int idaapi tms_get_frame_retsize(const func_t *pfn);
|
||||
int idaapi is_align_insn(ea_t ea);
|
||||
bool is_basic_block_end(const insn_t &insn); // 0-no, 2-yes
|
||||
|
||||
#endif // _TMS320C54_HPP
|
||||
Reference in New Issue
Block a user