update to ida 7.6, add builds
This commit is contained in:
415
idasdk76/module/tms320c6/reg.cpp
Normal file
415
idasdk76/module/tms320c6/reg.cpp
Normal file
@@ -0,0 +1,415 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-98 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@estar.msk.su
|
||||
* FIDO: 2:5020/209
|
||||
*
|
||||
*
|
||||
* TMS320C6xx - VLIW (very long instruction word) architecture
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tms6.hpp"
|
||||
int data_id;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// B14 - data page pointer
|
||||
// B15 - stack pointer
|
||||
static const char *const RegNames[] =
|
||||
{
|
||||
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
|
||||
"A8", "A9", "A10", "A11", "A12", "A13", "A14", "A15",
|
||||
"A16", "A17", "A18", "A19", "A20", "A21", "A22", "A23",
|
||||
"A24", "A25", "A26", "A27", "A28", "A29", "A30", "A31",
|
||||
"B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7",
|
||||
"B8", "B9", "B10", "B11", "B12", "B13", "B14", "B15",
|
||||
"B16", "B17", "B18", "B19", "B20", "B21", "B22", "B23",
|
||||
"B24", "B25", "B26", "B27", "B28", "B29", "B30", "B31",
|
||||
"AMR",
|
||||
"CSR",
|
||||
"IFR",
|
||||
"ISR",
|
||||
"ICR",
|
||||
"IER",
|
||||
"ISTP",
|
||||
"IRP",
|
||||
"NRP",
|
||||
"ACR", // undocumented, info from Jeff Bailey <jeff_bailey@infinitek.com>
|
||||
"ADR", // undocumented, info from Jeff Bailey <jeff_bailey@infinitek.com>
|
||||
"PCE1",
|
||||
"FADCR",
|
||||
"FAUCR",
|
||||
"FMCR",
|
||||
"TSCL",
|
||||
"TSCH",
|
||||
"ILC",
|
||||
"RILC",
|
||||
"REP",
|
||||
"DNUM",
|
||||
"SSR",
|
||||
"GPLYA",
|
||||
"GPLYB",
|
||||
"GFPGFR",
|
||||
"TSR",
|
||||
"ITSR",
|
||||
"NTSR",
|
||||
"ECR",
|
||||
"EFR",
|
||||
"IERR",
|
||||
"CS", "DS"
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list va)
|
||||
{
|
||||
switch ( code )
|
||||
{
|
||||
case idb_event::segm_moved: // A segment is moved
|
||||
// Fix processor dependent address sensitive information
|
||||
{
|
||||
ea_t from = va_arg(va, ea_t);
|
||||
ea_t to = va_arg(va, ea_t);
|
||||
asize_t size = va_arg(va, asize_t);
|
||||
bool changed_netmap = va_argi(va, bool);
|
||||
if ( !changed_netmap )
|
||||
{
|
||||
nodeidx_t ndx1 = ea2node(from);
|
||||
nodeidx_t ndx2 = ea2node(to);
|
||||
pm.helper.altshift(ndx1, ndx2, size);
|
||||
// like altadjust()
|
||||
for ( nodeidx_t ndx = pm.helper.supfirst();
|
||||
ndx != BADADDR;
|
||||
ndx = pm.helper.supnext(ndx) )
|
||||
{
|
||||
tgtinfo_t tgt;
|
||||
ea_t ea = node2ea(ndx);
|
||||
tgt.restore_from_idb(pm, ea);
|
||||
if ( tgt.has_target() )
|
||||
{
|
||||
tgt.target = correct_address(tgt.target, from, to, size);
|
||||
tgt.save_to_idb(pm, ea);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 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(tms6_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
ssize_t idaapi tms6_t::on_event(ssize_t msgid, va_list va)
|
||||
{
|
||||
int code = 0;
|
||||
switch ( msgid )
|
||||
{
|
||||
case processor_t::ev_init:
|
||||
hook_event_listener(HT_IDB, &idb_listener, &LPH);
|
||||
helper.create(PROCMOD_NODE_NAME);
|
||||
break;
|
||||
|
||||
case processor_t::ev_term:
|
||||
unhook_event_listener(HT_IDB, &idb_listener);
|
||||
clr_module_data(data_id);
|
||||
break;
|
||||
|
||||
case processor_t::ev_oldfile:
|
||||
{
|
||||
netnode old_tnode("$ tms node");
|
||||
if ( old_tnode != BADNODE )
|
||||
{
|
||||
upgrade_tnode(old_tnode);
|
||||
old_tnode.kill();
|
||||
}
|
||||
}
|
||||
// no break
|
||||
case processor_t::ev_ending_undo:
|
||||
case processor_t::ev_newfile:
|
||||
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_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_out_data:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
bool analyze_only = va_argi(va, bool);
|
||||
data(*ctx, analyze_only);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_special_item:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
uchar seg_type = va_argi(va, uchar);
|
||||
outspec(*ctx, seg_type);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_is_align_insn:
|
||||
{
|
||||
ea_t ea = va_arg(va, ea_t);
|
||||
return is_align_insn(ea);
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void tms6_t::upgrade_tnode(const netnode &old_tnode)
|
||||
{
|
||||
// copy branch/call info to HELPER
|
||||
for ( nodeidx_t ndx = old_tnode.altfirst();
|
||||
ndx != BADADDR;
|
||||
ndx = old_tnode.altnext(ndx) )
|
||||
{
|
||||
nodeidx_t ndx2 = old_tnode.altval(ndx);
|
||||
if ( ndx2 == 0 )
|
||||
continue;
|
||||
tgtinfo_t tgt;
|
||||
switch ( ndx2 )
|
||||
{
|
||||
case 1:
|
||||
tgt.type = tgtinfo_t::IND_BRANCH;
|
||||
break;
|
||||
case 2:
|
||||
tgt.type = tgtinfo_t::IND_CALL;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
ea_t target = node2ea(ndx2);
|
||||
tgt.type = (target & 1) != 0
|
||||
? tgtinfo_t::BRANCH
|
||||
: tgtinfo_t::CALL;
|
||||
tgt.target = target & ~1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
tgt.save_to_idb(*this, node2ea(ndx));
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
const char *tgtinfo_t::get_type_name() const
|
||||
{
|
||||
switch ( type )
|
||||
{
|
||||
case tgtinfo_t::CALL: return "CALL";
|
||||
case tgtinfo_t::BRANCH: return "BRANCH";
|
||||
case tgtinfo_t::IND_CALL: return "INDIRECT CALL";
|
||||
case tgtinfo_t::IND_BRANCH: return "INDIRECT BRANCH";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
#define TGTINFO_MAX_SIZE (1 + ea_packed_size)
|
||||
void tgtinfo_t::save_to_idb(tms6_t &pm, ea_t ea) const
|
||||
{
|
||||
uchar buf[TGTINFO_MAX_SIZE];
|
||||
uchar *ptr = buf;
|
||||
uchar *end = buf + sizeof(buf);
|
||||
ptr = pack_db(ptr, end, uchar(type));
|
||||
if ( has_target() )
|
||||
ptr = pack_ea(ptr, end, ea2node(target));
|
||||
pm.helper.supset_ea(ea, buf, ptr - buf);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
bool tgtinfo_t::restore_from_idb(const tms6_t &pm, ea_t ea)
|
||||
{
|
||||
uchar buf[TGTINFO_MAX_SIZE];
|
||||
ssize_t code = pm.helper.supval_ea(ea, buf, sizeof(buf));
|
||||
if ( code < 1 )
|
||||
return false;
|
||||
memory_deserializer_t mmdsr(buf, code);
|
||||
uchar t = mmdsr.unpack_db();
|
||||
if ( t > IND_BRANCH )
|
||||
return false;
|
||||
type = type_t(t);
|
||||
if ( has_target() )
|
||||
target = node2ea(mmdsr.unpack_ea());
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// TMS320C6x COFF Assembler
|
||||
//-----------------------------------------------------------------------
|
||||
static const asm_t dspasm =
|
||||
{
|
||||
AS_COLON | ASH_HEXF0 | ASD_DECF0 | ASB_BINF0 | ASO_OCTF5,
|
||||
0,
|
||||
"TMS320C6x COFF Assembler",
|
||||
0,
|
||||
NULL, // header lines
|
||||
NULL, // org
|
||||
".end",
|
||||
|
||||
";", // comment string
|
||||
'"', // string delimiter
|
||||
'\'', // char delimiter
|
||||
"\\\"'", // special symbols in char and string constants
|
||||
|
||||
".string", // ascii string directive
|
||||
".char", // byte directive
|
||||
".short", // word directive
|
||||
".long", // double words
|
||||
NULL, // no qwords
|
||||
NULL, // oword (16 bytes)
|
||||
NULL, // float (4 bytes)
|
||||
NULL, // double (8 bytes)
|
||||
NULL, // tbyte (10/12 bytes)
|
||||
NULL, // packed decimal real
|
||||
NULL, // arrays (#h,#d,#v,#s(...)
|
||||
".space %s", // uninited arrays
|
||||
".set", // equ
|
||||
NULL, // 'seg' prefix (example: push seg seg001)
|
||||
"$", // current IP (instruction pointer)
|
||||
NULL, // func_header
|
||||
NULL, // func_footer
|
||||
".def", // "public" name keyword
|
||||
NULL, // "weak" name keyword
|
||||
".ref", // "extrn" name keyword
|
||||
".usect", // "comm" (communal variable)
|
||||
NULL, // get_type_name
|
||||
".align", // "align" keyword
|
||||
'(', ')', // lbrace, rbrace
|
||||
NULL, // mod
|
||||
"&", // and
|
||||
"|", // or
|
||||
"^", // xor
|
||||
"!", // not
|
||||
"<<", // shl
|
||||
">>", // shr
|
||||
NULL, // sizeof
|
||||
};
|
||||
|
||||
|
||||
static const asm_t *const asms[] = { &dspasm, NULL };
|
||||
//-----------------------------------------------------------------------
|
||||
#define FAMILY "TMS320C6 series:"
|
||||
static const char *const shnames[] = { "TMS320C6", NULL };
|
||||
static const char *const lnames[] =
|
||||
{
|
||||
FAMILY"Texas Instruments TMS320C6xxx",
|
||||
NULL
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const uchar retcode_1[] = { 0x62, 0x63, 0x0C, 0x00 };
|
||||
|
||||
static const bytes_t retcodes[] =
|
||||
{
|
||||
{ sizeof(retcode_1), retcode_1 },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Processor Definition
|
||||
//-----------------------------------------------------------------------
|
||||
processor_t LPH =
|
||||
{
|
||||
IDP_INTERFACE_VERSION, // version
|
||||
PLFM_TMSC6, // id
|
||||
// flag
|
||||
PR_USE32
|
||||
| PR_DEFSEG32
|
||||
| PR_DELAYED
|
||||
| PR_ALIGN_INSN, // allow align instructions
|
||||
// flag2
|
||||
0,
|
||||
8, // 8 bits in a byte for code segments
|
||||
8, // 8 bits in a byte for other segments
|
||||
|
||||
shnames,
|
||||
lnames,
|
||||
|
||||
asms,
|
||||
|
||||
notify,
|
||||
|
||||
RegNames, // Register names
|
||||
qnumber(RegNames), // Number of registers
|
||||
|
||||
rVcs, // first
|
||||
rVds, // last
|
||||
0, // size of a segment register
|
||||
rVcs, rVds,
|
||||
|
||||
NULL, // No known code start sequences
|
||||
retcodes,
|
||||
|
||||
TMS6_null,
|
||||
TMS6_last,
|
||||
Instructions, // instruc
|
||||
0, // int tbyte_size;
|
||||
{ 2, 4, 8, 12 }, // char real_width[4];
|
||||
TMS6_null, // Icode of return instruction. It is ok to give any of possible return instructions
|
||||
};
|
||||
Reference in New Issue
Block a user